From f5c4671bfbad96bf346bd7e9a21fc4317b4959df Mon Sep 17 00:00:00 2001 From: Indrajith K L Date: Sat, 3 Dec 2022 17:00:20 +0530 Subject: Adds most of the tools --- v_windows/v/old/vlib/dl/dl.v | 48 ++++++++++++++++++++++++++++++++++ v_windows/v/old/vlib/dl/dl_nix.c.v | 43 ++++++++++++++++++++++++++++++ v_windows/v/old/vlib/dl/dl_test.v | 46 ++++++++++++++++++++++++++++++++ v_windows/v/old/vlib/dl/dl_windows.c.v | 39 +++++++++++++++++++++++++++ 4 files changed, 176 insertions(+) create mode 100644 v_windows/v/old/vlib/dl/dl.v create mode 100644 v_windows/v/old/vlib/dl/dl_nix.c.v create mode 100644 v_windows/v/old/vlib/dl/dl_test.v create mode 100644 v_windows/v/old/vlib/dl/dl_windows.c.v (limited to 'v_windows/v/old/vlib/dl') diff --git a/v_windows/v/old/vlib/dl/dl.v b/v_windows/v/old/vlib/dl/dl.v new file mode 100644 index 0000000..04ad16b --- /dev/null +++ b/v_windows/v/old/vlib/dl/dl.v @@ -0,0 +1,48 @@ +module dl + +pub const ( + version = 1 + dl_ext = get_shared_library_extension() +) + +// get_shared_library_extension returns the platform dependent shared library extension +// i.e. .dll on windows, .so on most unixes, .dylib on macos. +[inline] +pub fn get_shared_library_extension() string { + return $if windows { + '.dll' + } $else $if macos { + '.dylib' + } $else { + '.so' + } +} + +// get_libname returns a library name with the operating system specific extension for +// shared libraries. +[inline] +pub fn get_libname(libname string) string { + return '$libname$dl.dl_ext' +} + +// open_opt - loads the dynamic shared object. +// Unlike open, open_opt return an option. +pub fn open_opt(filename string, flags int) ?voidptr { + shared_object_handle := open(filename, flags) + if shared_object_handle == 0 { + e := dlerror() + return error(e) + } + return shared_object_handle +} + +// sym_opt returns the address of a symbol in a given shared object, if found. +// Unlike sym, sym_opt returns an option. +pub fn sym_opt(shared_object_handle voidptr, symbol string) ?voidptr { + sym_handle := sym(shared_object_handle, symbol) + if sym_handle == 0 { + e := dlerror() + return error(e) + } + return sym_handle +} diff --git a/v_windows/v/old/vlib/dl/dl_nix.c.v b/v_windows/v/old/vlib/dl/dl_nix.c.v new file mode 100644 index 0000000..40f63b5 --- /dev/null +++ b/v_windows/v/old/vlib/dl/dl_nix.c.v @@ -0,0 +1,43 @@ +module dl + +#include + +$if linux { + #flag -ldl +} + +pub const ( + rtld_now = C.RTLD_NOW + rtld_lazy = C.RTLD_LAZY +) + +fn C.dlopen(filename &char, flags int) voidptr + +fn C.dlsym(handle voidptr, symbol &char) voidptr + +fn C.dlclose(handle voidptr) int + +fn C.dlerror() &char + +// open loads the dynamic shared object. +pub fn open(filename string, flags int) voidptr { + return C.dlopen(&char(filename.str), flags) +} + +// close frees a given shared object. +pub fn close(handle voidptr) bool { + return C.dlclose(handle) == 0 +} + +// sym returns an address of a symbol in a given shared object. +pub fn sym(handle voidptr, symbol string) voidptr { + return C.dlsym(handle, &char(symbol.str)) +} + +// dlerror provides a text error diagnostic message for functions in `dl` +// it returns a human-readable string, describing the most recent error +// that occurred from a call to one of the `dl` functions, since the last +// call to dlerror() +pub fn dlerror() string { + return unsafe { cstring_to_vstring(C.dlerror()) } +} diff --git a/v_windows/v/old/vlib/dl/dl_test.v b/v_windows/v/old/vlib/dl/dl_test.v new file mode 100644 index 0000000..c4f0824 --- /dev/null +++ b/v_windows/v/old/vlib/dl/dl_test.v @@ -0,0 +1,46 @@ +import dl + +fn test_dl() { + $if linux { + run_test_invalid_lib_linux() + return + } + $if windows { + run_test_invalid_lib_windows() + run_test_valid_lib_windows() + run_test_invalid_sym_windows() + run_test_valid_sym_windows() + return + } $else { + eprint('currently not implemented on this platform') + } +} + +fn run_test_invalid_lib_linux() { + // ensure a not-existing dl won't be loaded + h := dl.open('not-existing-dynamic-link-library', dl.rtld_now) + assert h == 0 +} + +fn run_test_invalid_lib_windows() { + // ensure a not-existing dl won't be loaded + h := dl.open('not-existing-dynamic-link-library', dl.rtld_now) + assert h == 0 +} + +fn run_test_valid_lib_windows() { + h := dl.open('shell32', dl.rtld_now) + assert h != 0 +} + +fn run_test_invalid_sym_windows() { + h := dl.open('shell32', dl.rtld_now) + proc := dl.sym(h, 'CommandLineToArgvW2') + assert proc == 0 +} + +fn run_test_valid_sym_windows() { + h := dl.open('shell32', dl.rtld_now) + proc := dl.sym(h, 'CommandLineToArgvW') + assert proc != 0 +} diff --git a/v_windows/v/old/vlib/dl/dl_windows.c.v b/v_windows/v/old/vlib/dl/dl_windows.c.v new file mode 100644 index 0000000..b6ae2fc --- /dev/null +++ b/v_windows/v/old/vlib/dl/dl_windows.c.v @@ -0,0 +1,39 @@ +module dl + +pub const ( + rtld_now = 0 + rtld_lazy = 0 +) + +fn C.LoadLibrary(libfilename &u16) voidptr + +fn C.GetProcAddress(handle voidptr, procname &byte) voidptr + +fn C.FreeLibrary(handle voidptr) bool + +// open loads a given module into the address space of the calling process. +pub fn open(filename string, flags int) voidptr { + res := C.LoadLibrary(filename.to_wide()) + return res +} + +// close frees the loaded a given module. +pub fn close(handle voidptr) bool { + return C.FreeLibrary(handle) +} + +// sym returns an address of an exported function or variable from a given module. +pub fn sym(handle voidptr, symbol string) voidptr { + return C.GetProcAddress(handle, symbol.str) +} + +// dlerror provides a text error diagnostic message for functions in `dl` +// it returns a human-readable string, describing the most recent error +// that occurred from a call to one of the `dl` functions, since the last +// call to dlerror() +pub fn dlerror() string { + // https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror + // Unlike dlerror(), GetLastError returns just an error code, that is function specific. + cerr := int(C.GetLastError()) + return 'error code $cerr' +} -- cgit v1.2.3