mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
154 lines
3.9 KiB
V
154 lines
3.9 KiB
V
|
[has_globals]
|
||
|
module loader
|
||
|
|
||
|
import dl
|
||
|
import os
|
||
|
|
||
|
const (
|
||
|
dl_no_path_issue_msg = 'no paths to dynamic library'
|
||
|
dl_open_issue_msg = 'could not open dynamic library'
|
||
|
dl_sym_issue_msg = 'could not get optional symbol from dynamic library'
|
||
|
dl_close_issue_msg = 'could not close dynamic library'
|
||
|
dl_register_issue_msg = 'could not register dynamic library loader'
|
||
|
)
|
||
|
|
||
|
pub const (
|
||
|
dl_no_path_issue_code = 1
|
||
|
dl_open_issue_code = 1
|
||
|
dl_sym_issue_code = 2
|
||
|
dl_close_issue_code = 3
|
||
|
dl_register_issue_code = 4
|
||
|
|
||
|
dl_no_path_issue_err = error_with_code(dl_no_path_issue_msg, dl_no_path_issue_code)
|
||
|
dl_open_issue_err = error_with_code(dl_open_issue_msg, dl_open_issue_code)
|
||
|
dl_sym_issue_err = error_with_code(dl_sym_issue_msg, dl_sym_issue_code)
|
||
|
dl_close_issue_err = error_with_code(dl_close_issue_msg, dl_close_issue_code)
|
||
|
dl_register_issue_err = error_with_code(dl_register_issue_msg, dl_register_issue_code)
|
||
|
)
|
||
|
|
||
|
__global (
|
||
|
registered_dl_loaders map[string]&DynamicLibLoader
|
||
|
)
|
||
|
|
||
|
fn register_dl_loader(dl_loader &DynamicLibLoader) ! {
|
||
|
if dl_loader.key in registered_dl_loaders {
|
||
|
return loader.dl_register_issue_err
|
||
|
}
|
||
|
registered_dl_loaders[dl_loader.key] = dl_loader
|
||
|
}
|
||
|
|
||
|
// registered_dl_loader_keys returns the keys of registered DynamicLibLoader.
|
||
|
pub fn registered_dl_loader_keys() []string {
|
||
|
return registered_dl_loaders.keys()
|
||
|
}
|
||
|
|
||
|
// DynamicLibLoader is a wrapper around dlopen, dlsym and dlclose.
|
||
|
[heap]
|
||
|
pub struct DynamicLibLoader {
|
||
|
pub:
|
||
|
key string
|
||
|
flags int = dl.rtld_lazy
|
||
|
paths []string
|
||
|
mut:
|
||
|
handle voidptr
|
||
|
sym_map map[string]voidptr
|
||
|
}
|
||
|
|
||
|
// DynamicLibLoaderConfig is a configuration for DynamicLibLoader.
|
||
|
[params]
|
||
|
pub struct DynamicLibLoaderConfig {
|
||
|
// flags is the flags for dlopen.
|
||
|
flags int = dl.rtld_lazy
|
||
|
// key is the key to register the DynamicLibLoader.
|
||
|
key string
|
||
|
// env_path is the environment variable name that contains the path to the dynamic library.
|
||
|
env_path string
|
||
|
// paths is the list of paths to the dynamic library.
|
||
|
paths []string
|
||
|
}
|
||
|
|
||
|
// new_dynamic_lib_loader returns a new DynamicLibLoader.
|
||
|
fn new_dynamic_lib_loader(conf DynamicLibLoaderConfig) !&DynamicLibLoader {
|
||
|
mut paths := []string{}
|
||
|
|
||
|
if conf.env_path.len > 0 {
|
||
|
if env_path := os.getenv_opt(conf.env_path) {
|
||
|
paths << env_path.split(os.path_delimiter)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
paths << conf.paths
|
||
|
|
||
|
if paths.len == 0 {
|
||
|
return loader.dl_no_path_issue_err
|
||
|
}
|
||
|
|
||
|
mut dl_loader := &DynamicLibLoader{
|
||
|
key: conf.key
|
||
|
flags: conf.flags
|
||
|
paths: paths
|
||
|
}
|
||
|
|
||
|
register_dl_loader(dl_loader)!
|
||
|
return dl_loader
|
||
|
}
|
||
|
|
||
|
// get_or_create_dynamic_lib_loader returns a DynamicLibLoader.
|
||
|
// If the DynamicLibLoader is not registered, it creates a new DynamicLibLoader.
|
||
|
pub fn get_or_create_dynamic_lib_loader(conf DynamicLibLoaderConfig) !&DynamicLibLoader {
|
||
|
if dl_loader := registered_dl_loaders[conf.key] {
|
||
|
return dl_loader
|
||
|
}
|
||
|
return new_dynamic_lib_loader(conf)
|
||
|
}
|
||
|
|
||
|
// load loads the dynamic library.
|
||
|
pub fn (mut dl_loader DynamicLibLoader) open() !voidptr {
|
||
|
if !isnil(dl_loader.handle) {
|
||
|
return dl_loader.handle
|
||
|
}
|
||
|
|
||
|
for path in dl_loader.paths {
|
||
|
if handle := dl.open_opt(path, dl_loader.flags) {
|
||
|
dl_loader.handle = handle
|
||
|
return handle
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return loader.dl_open_issue_err
|
||
|
}
|
||
|
|
||
|
// close closes the dynamic library.
|
||
|
pub fn (mut dl_loader DynamicLibLoader) close() ! {
|
||
|
if !isnil(dl_loader.handle) {
|
||
|
if dl.close(dl_loader.handle) {
|
||
|
dl_loader.handle = unsafe { nil }
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return loader.dl_close_issue_err
|
||
|
}
|
||
|
|
||
|
// get_sym gets a symbol from the dynamic library.
|
||
|
pub fn (mut dl_loader DynamicLibLoader) get_sym(name string) !voidptr {
|
||
|
if sym := dl_loader.sym_map[name] {
|
||
|
return sym
|
||
|
}
|
||
|
|
||
|
handle := dl_loader.open()!
|
||
|
if sym := dl.sym_opt(handle, name) {
|
||
|
dl_loader.sym_map[name] = sym
|
||
|
return sym
|
||
|
}
|
||
|
|
||
|
dl_loader.close()!
|
||
|
return loader.dl_sym_issue_err
|
||
|
}
|
||
|
|
||
|
// unregister unregisters the DynamicLibLoader.
|
||
|
pub fn (mut dl_loader DynamicLibLoader) unregister() {
|
||
|
dl_loader.close() or {}
|
||
|
registered_dl_loaders.delete(dl_loader.key)
|
||
|
}
|