package dl import ( "errors" "unsafe" ) //#cgo LDFLAGS: -ldl //#include //#include import "C" type Flag int const ( RTLD_LAZY Flag = C.RTLD_LAZY // Relocations are performed at an // implementation-defined time. RTLD_NOW Flag = C.RTLD_NOW // Relocations are performed when the // object is loaded. RTLD_GLOBAL Flag = C.RTLD_GLOBAL // All symbols are available for // relocation processing of other // modules. RTLD_LOCAL Flag = C.RTLD_LOCAL // All symbols are not made available // for relocation processing by other // modules. ) type Handle struct { c unsafe.Pointer } func Open(name string, flags Flag) (Handle, error) { nameC := C.CString(name) defer C.free(unsafe.Pointer(nameC)) dlerror() ptr := C.dlopen(nameC, C.int(flags)) if ptr == nil { return Handle{}, dlerror() } return Handle{ptr}, nil } // This returns uintptr instead of unsafe.Pointer so that code using // reflect cannot obtain unsafe.Pointers without importing the unsafe // package explicitly. func (h Handle) Sym(symbol string) (uintptr, error) { symbolC := C.CString(symbol) defer C.free(unsafe.Pointer(symbolC)) dlerror() ptr := C.dlsym(h.c, symbolC) if ptr == nil { return 0, dlerror() } return uintptr(ptr), nil } func (h Handle) Close() error { dlerror() r := C.dlclose(h.c) if r != 0 { return dlerror() } return nil } func dlerror() error { strC := C.dlerror() if strC == nil { return nil } return errors.New(C.GoString(strC)) }