summaryrefslogtreecommitdiff
path: root/src/dl/dlfcn.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/dl/dlfcn.go')
-rw-r--r--src/dl/dlfcn.go74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/dl/dlfcn.go b/src/dl/dlfcn.go
new file mode 100644
index 0000000..d5467f3
--- /dev/null
+++ b/src/dl/dlfcn.go
@@ -0,0 +1,74 @@
+package dl
+
+import (
+ "errors"
+ "unsafe"
+)
+
+//#cgo LDFLAGS: -ldl
+//#include <stdlib.h>
+//#include <dlfcn.h>
+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))
+}