Golang call functions from shared c library using cgo

Viewed 1398

I'm pretty new to more low level programming languages, so sorry if the answer is totally obvious.

For a project I need to import a shared library (sdk.so) and call its functions. With nm -D /lib/sdk.so --defined-only I can view the exported functions, so I know that they exist.

Now I want to call certain functions, so I load the library:

package main

// #cgo LDFLAGS: -ldl
// #include <stdlib.h>
// #include <dlfcn.h>

import "C"

import (
    "errors"
    "fmt"
    "log"
    "unsafe"
)

libName := "sdk"

libName := C.CString(name)
defer C.free(unsafe.Pointer(libName))

handle := C.dlopen(libName, C.RTLD_LAZY)

if handle == nil {
    return nil, ErrSoNotFound
}

sym := C.CString("some_function")
defer C.free(unsafe.Pointer(sym))

someFunction := C.dlsym(handle, sym)
if mdpSdkAlloc == nil {
    log.Fatal(ErrSoFunctionNotFound)
}

fmt.Println(someFunction)

But now I'm stuck and don't know how to call the function. The Println prints something like 0x7f50a5f9cec0, with an ampersand I'm getting something like 0xc0000b2018 and with an asterisk I'm getting "invalid indirect of someFunction (type unsafe.Pointer)". How can i cast this to a function call?

Thanks for any help.

1 Answers

You have to define a pointer to your function in /* */import "C" section. Then you can initialize the pointer with the result of dlsym call. Then you can call your function like C.your_function(...some arguments).

By the way, you can try to use my go-dl package to simplify it https://github.com/sudachen/go-dl

The go-dl uses the declarative specification of places where the shared library can be found. For example, we want to search the shared library in system libraries, some custom place and then if nothing found download and/or load from cache.

   so := dl.Load(
       // firstly do search for system libraries
        dl.System("libsdk.so"),
       // then in the some custom place, 
       // it can be specified many times for different places
        dl.Custom("/opt/sdk/libsdk.so"), 
       // in download cache
        dl.Cached("sdk/sdk.so"), 
       // if nothing found download to cache and use cache
        dl.LzmaExternal(urlbase+"sdk.so.xz"))  

However, you still have to define the C function pointer to bind library symbols by SO.Bind(...) method. Try to look at tests for more information about how it can be used.

Related