Below is a working example in C. Once you have that going, then add the CGO layer on top to call from Go. Note I seem to recall you might have to mark your C function as //extern ...maybe, if in a separate C file and not inline in the .go file... read the CGO docs in full for details.
$ cat libexample.c #include <stdio.h> int multiply(int a, int b) { return a * b; } $ gcc -shared -o libexample.so -fPIC libexample.c $ cat dynamic_loading.c #include <stdio.h> #include <dlfcn.h> #include <stdlib.h> int main() { // Open the shared library void* handle = dlopen("./libexample.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "Error loading library: %s\n", dlerror()); return 1; } // Get the function pointer by name int (*multiply)(int, int) = dlsym(handle, "multiply"); if (!multiply) { fprintf(stderr, "Error finding function: %s\n", dlerror()); dlclose(handle); return 1; } // Call the function int result = multiply(5, 7); printf("5 * 7 = %d\n", result); // Clean up dlclose(handle); return 0; } $ gcc -o user_of_library dynamic_loading.c $ ./user_of_library 5 * 7 = 35 Go host, from AI but does run package main /* #cgo LDFLAGS: -ldl #include <dlfcn.h> #include <stdlib.h> #include <stdio.h> // Define the function type that matches our C function typedef int (*multiply_func)(int, int); // Helper function to load and call the multiply function int call_multiply(int a, int b) { void* handle = dlopen("./libexample.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "Error loading library: %s\n", dlerror()); return -1; } // not C, but you'll need the moral equivalent of // defer dlclose(handle); // to clean up. multiply_func multiply = (multiply_func)dlsym(handle, "multiply"); if (!multiply) { fprintf(stderr, "Error finding function: %s\n", dlerror()); return -1; } return multiply(a, b); } */ import "C" import "fmt" func main() { // Call the C function through our wrapper result := C.call_multiply(C.int(5), C.int(7)) if result == -1 { fmt.Println("Error calling multiply function") return } fmt.Printf("5 * 7 = %d\n", int(result)) } $ go run user_of_lib_from_go.go 5 * 7 = 35 On Thursday, May 15, 2025 at 10:45:00 AM UTC+1 Bruno Albuquerque wrote: > You can not directly call a C function pointer from Go. You will need a > CGO wrapper that calls it and them you call that wrapper from Go. > > -Bruno > > > On Thu, May 15, 2025, 5:20 AM rudeus greyrat <rudeusqu...@gmail.com> > wrote: > >> Hello, >> >> Thanks for your answer. >> >> Three points to note: >> >> - I never asked how to create an so, I already have a given so :/ >> - No need to provide the code because the issue is simple to >> describe: I have an address of a function in a Go variable, how to call >> it ? >> - AI is garbage (even though I use it) >> >> I thought about using assembly with a call instruction but I hoped >> someone knowledgable would tell me there is a built in Go function for that. >> >> Regards, >> Rudeus >> >> >> >> Le jeudi 15 mai 2025 à 02:46:18 UTC+2, Kurtis Rader a écrit : >> >>> On Wed, May 14, 2025 at 4:17 PM rudeus greyrat <rudeusqu...@gmail.com> >>> wrote: >>> >>>> I am still a beginner in Linux internals so please bear with me. >>>> >>>> I have a ".so" that export "helloworld" function. >>>> >>>> I load the ".so" using CGO by: >>>> >>>> 1. Creating a file descriptor >>>> 2. using ```write``` to write the so to it >>>> >>>> A shared library (".so" file) has a complex structure. You normally >>> create one using a compiler and related tools. For example, the Go compiler >>> can create a .so file from Go source code using a command like >>> >>> go build -buildmode=c-shared -o mylib.so >>> >>> It seems unlikely you are creating a valid .so file by opening an empty >>> file and writing to it unless you are simply copying one .so file to >>> another file. >>> >>>> >>>> 1. Get a handle using ```dlopen``` >>>> 2. Get the address of ```helloworld``` symbol using ```dlsym``` >>>> >>>> The address of "helloworld" is saved in a go variable called >>>> ```address``` >>>> >>>> How to call ```address``` ? >>>> >>>> On windows I am able to call address using ```syscall.SyscallN```. On >>>> Linux I tried with >>>> ``` >>>> r1, r2, err := syscall.Syscall(address, 0, 0, 0) >>>> ``` >>>> >>>> And I get "function not implemented" error. >>>> >>> >>> I can't speak to Windows but on Unix like operating systems, such as >>> Linux, a function in a shared library is a user space function, not a >>> kernel entry point. A syscall is the way you call OS kernel functions, not >>> user space functions. I wouldn't expect syscall.Syscall() to work on >>> Windows when passed the address of a function in a DLL. Did you actually >>> confirm that it does work when passed the address of a DLL user space >>> function? In any case this definitely won't work on Linux. >>> >>> I searched for "how to call a function in a shared library in go" in >>> Chrome and the results included an AI generated example of how to do this >>> along with links to many articles and other sources such as StackOverflow. >>> If you're still having problems ask again but show us the source code you >>> wrote and the commands you ran to compile it. >>> >>> -- >>> Kurtis Rader >>> Caretaker of the exceptional canines Junior and Hank >>> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com. >> To view this discussion visit >> https://groups.google.com/d/msgid/golang-nuts/6df9116e-d5dd-4b93-bd0d-45df42c24626n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/6df9116e-d5dd-4b93-bd0d-45df42c24626n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/e29eac0a-6735-4e13-a90c-cc4e14572587n%40googlegroups.com.