🎨 optimize implementation of dlopen
This commit is contained in:
parent
456ed5c782
commit
bbd4d1907b
|
@ -639,11 +639,11 @@ Windows(`.dll`):
|
|||
|
||||
`g++ -shared -o libfib.dll fib.o`
|
||||
|
||||
Then we write a test nasal file to run this fib function, using `os.platform()` we could write a cross-platform program:
|
||||
Then we write a test nasal file to run this fib function:
|
||||
|
||||
```javascript
|
||||
use std.dylib;
|
||||
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||
var dlhandle = dylib.dlopen("libfib");
|
||||
var fib = dlhandle.fib;
|
||||
for(var i = 1; i<30; i += 1)
|
||||
println(dylib.dlcall(fib, i));
|
||||
|
@ -660,7 +660,7 @@ dylib.dlclose(dlhandle.lib);
|
|||
|
||||
```javascript
|
||||
use std.dylib;
|
||||
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||
var dlhandle = dylib.dlopen("libfib");
|
||||
var fib = dlhandle.fib;
|
||||
var invoke = dylib.limitcall(1); # this means the called function has only one parameter
|
||||
for(var i = 1; i<30; i += 1)
|
||||
|
|
|
@ -618,12 +618,11 @@ Windows(`.dll`):
|
|||
|
||||
`g++ -shared -o libfib.dll fib.o`
|
||||
|
||||
好了,那么我们可以写一个测试用的nasal代码来运行这个斐波那契函数了。
|
||||
下面例子中`os.platform()`是用来检测当前运行的系统环境的,这样可以实现跨平台:
|
||||
好了,那么我们可以写一个测试用的nasal代码来运行这个斐波那契函数了:
|
||||
|
||||
```javascript
|
||||
use std.dylib;
|
||||
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||
var dlhandle = dylib.dlopen("libfib");
|
||||
var fib = dlhandle.fib;
|
||||
for(var i = 1; i<30; i += 1)
|
||||
println(dylib.dlcall(fib, i));
|
||||
|
@ -640,7 +639,7 @@ dylib.dlclose(dlhandle.lib);
|
|||
|
||||
```javascript
|
||||
use std.dylib;
|
||||
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||
var dlhandle = dylib.dlopen("libfib");
|
||||
var fib = dlhandle.fib;
|
||||
var invoke = dylib.limitcall(1); # this means the called function has only one parameter
|
||||
for(var i = 1; i<30; i += 1)
|
||||
|
|
2
makefile
2
makefile
|
@ -189,6 +189,8 @@ build/dylib_lib.o: \
|
|||
src/nasal.h\
|
||||
src/nasal_type.h\
|
||||
src/nasal_gc.h\
|
||||
src/util/util.h\
|
||||
src/util/fs.h\
|
||||
src/natives/dylib_lib.h src/natives/dylib_lib.cpp | build
|
||||
$(CXX) $(CXXFLAGS) src/natives/dylib_lib.cpp -o build/dylib_lib.o
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std.dylib;
|
||||
use std.os;
|
||||
|
||||
var _dl = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||
var _dl = dylib.dlopen("libfib");
|
||||
|
||||
var _fib = _dl.fib;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ var (
|
|||
getch,
|
||||
nonblock
|
||||
) = func {
|
||||
var lib = dylib.dlopen("libkey"~(os.platform()=="windows"? ".dll":".so"));
|
||||
var lib = dylib.dlopen("libkey");
|
||||
var kb = lib.nas_kbhit;
|
||||
var gt = lib.nas_getch;
|
||||
var nb = lib.nas_noblock;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std.dylib;
|
||||
use std.os;
|
||||
|
||||
var _dl = dylib.dlopen("libmat."~(os.platform()=="windows"?"dll":"so"));
|
||||
var _dl = dylib.dlopen("libmat");
|
||||
|
||||
var _vec2 = _dl.nas_vec2;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std.dylib;
|
|||
use std.os;
|
||||
|
||||
var socket = func() {
|
||||
var lib = dylib.dlopen("libnasock"~(os.platform()=="windows"? ".dll":".so"));
|
||||
var lib = dylib.dlopen("libnasock");
|
||||
|
||||
var sock = lib.nas_socket;
|
||||
var closesocket = lib.nas_closesocket;
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
#include "natives/dylib_lib.h"
|
||||
#include "util/util.h"
|
||||
#include "util/fs.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
namespace nasal {
|
||||
|
||||
const auto dynamic_library_type_name = "dylib";
|
||||
const auto function_address_type_name = "faddr";
|
||||
const auto dynamic_library_type_name = "nasal::dynamic_library";
|
||||
const auto function_address_type_name = "nasal::function_address";
|
||||
|
||||
void dynamic_library_destructor(void* pointer) {
|
||||
#ifdef _WIN32
|
||||
|
@ -13,33 +18,74 @@ void dynamic_library_destructor(void* pointer) {
|
|||
#endif
|
||||
}
|
||||
|
||||
std::string search_dynamic_library_path(const std::string& dlname) {
|
||||
const auto ext = (util::is_windows()? ".dll":".so");
|
||||
const auto lib_path = (util::is_windows()? ".\\":"./") + dlname + ext;
|
||||
if (fs::exists(lib_path)) {
|
||||
return lib_path;
|
||||
}
|
||||
const auto env_path = std::string(getenv("PATH"));
|
||||
const auto sep = (util::is_windows()? ";":":");
|
||||
|
||||
// do split string
|
||||
std::vector<std::string> env_path_vec = {};
|
||||
usize last = 0;
|
||||
usize pos = env_path.find(sep, 0);
|
||||
while(pos!=std::string::npos) {
|
||||
if (pos>last) {
|
||||
env_path_vec.push_back(env_path.substr(last, pos-last));
|
||||
}
|
||||
last = pos + 1;
|
||||
pos = env_path.find(sep, last);
|
||||
}
|
||||
if (last!=env_path.length()) {
|
||||
env_path_vec.push_back(env_path.substr(last));
|
||||
}
|
||||
|
||||
const auto path_front = util::is_windows()? "\\module\\":"/module/";
|
||||
for(auto& p : env_path_vec) {
|
||||
p += path_front + lib_path;
|
||||
if (fs::exists(p)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
var builtin_dlopen(context* ctx, gc* ngc) {
|
||||
auto dlname = ctx->localr[1];
|
||||
if (!dlname.is_str()) {
|
||||
auto dl = ctx->localr[1];
|
||||
if (!dl.is_str()) {
|
||||
return nas_err("dylib::dlopen", "\"libname\" must be string");
|
||||
}
|
||||
|
||||
const auto dlname = search_dynamic_library_path(dl.str());
|
||||
if (dlname.empty()) {
|
||||
return nas_err("dylib::dlopen",
|
||||
"cannot find dynamic lib <" + dl.str() + ">"
|
||||
);
|
||||
}
|
||||
|
||||
// get library pointer
|
||||
#ifdef _WIN32
|
||||
wchar_t* wide_string = new wchar_t[dlname.str().size()+1];
|
||||
wchar_t* wide_string = new wchar_t[dlname.size()+1];
|
||||
if (!wide_string) {
|
||||
return nas_err("dylib::dlopen", "malloc failed");
|
||||
}
|
||||
memset(wide_string, 0, sizeof(wchar_t) * dlname.str().size() + 1);
|
||||
mbstowcs(wide_string, dlname.str().c_str(), dlname.str().size() + 1);
|
||||
memset(wide_string, 0, sizeof(wchar_t) * dlname.size() + 1);
|
||||
mbstowcs(wide_string, dlname.c_str(), dlname.size() + 1);
|
||||
// load library by using wide string name
|
||||
void* dynamic_library_pointer = LoadLibraryA(dlname.str().c_str());
|
||||
void* dynamic_library_pointer = LoadLibraryA(dlname.c_str());
|
||||
delete []wide_string;
|
||||
#else
|
||||
void* dynamic_library_pointer = dlopen(
|
||||
dlname.str().c_str(), RTLD_LOCAL|RTLD_LAZY
|
||||
dlname.c_str(), RTLD_LOCAL|RTLD_LAZY
|
||||
);
|
||||
#endif
|
||||
|
||||
// check library pointer and insert into returned hashmap
|
||||
if (!dynamic_library_pointer) {
|
||||
return nas_err("dylib::dlopen",
|
||||
"cannot open dynamic lib <" + dlname.str() + ">"
|
||||
"cannot open dynamic lib <" + dl.str() + ">"
|
||||
);
|
||||
}
|
||||
auto return_hash = ngc->temp = ngc->alloc(vm_type::vm_hash);
|
||||
|
|
|
@ -11,10 +11,15 @@
|
|||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
namespace nasal {
|
||||
|
||||
void dynamic_library_destructor(void*);
|
||||
|
||||
std::string search_dynamic_library_path(const std::string&);
|
||||
|
||||
var builtin_dlopen(context*, gc*);
|
||||
var builtin_dlclose(context*, gc*);
|
||||
var builtin_dlcallv(context*, gc*);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace nasal {
|
||||
|
||||
const auto file_type_name = "file";
|
||||
const auto file_type_name = "nasal::FILE";
|
||||
|
||||
void filehandle_destructor(void* ptr) {
|
||||
fclose(static_cast<FILE*>(ptr));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace nasal {
|
||||
|
||||
const auto dir_type_name = "dir";
|
||||
const auto dir_type_name = "nasal::DIR";
|
||||
|
||||
void dir_entry_destructor(void* ptr) {
|
||||
#ifndef _MSC_VER
|
||||
|
|
|
@ -8,22 +8,6 @@ use std.unix;
|
|||
|
||||
# open dynamic lib. return a hash including dl pointer and function pointers
|
||||
var dlopen = func(libname) {
|
||||
# find dynamic lib from local dir first
|
||||
libname = (os.platform()=="windows"? ".\\":"./")~libname;
|
||||
if (io.exists(libname))
|
||||
return __dlopen(libname);
|
||||
# find dynamic lib through PATH
|
||||
var envpath = split(os.platform()=="windows"? ";":":", unix.getenv("PATH"));
|
||||
# first find ./module
|
||||
append(envpath, ".");
|
||||
var path = os.platform()=="windows"? "\\module\\":"/module/";
|
||||
foreach(var p;envpath) {
|
||||
p ~= path~libname;
|
||||
if (io.exists(p)) {
|
||||
libname = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return __dlopen(libname);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ func() {
|
|||
}();
|
||||
|
||||
var speed_test = func() {
|
||||
var dd = dylib.dlopen("libfib."~(os.platform()=="windows"? "dll":"so"));
|
||||
var dd = dylib.dlopen("libfib");
|
||||
println("[dylib ] ", dd);
|
||||
var fd = dd.quick_fib;
|
||||
var vec_call = dylib.dlcall;
|
||||
|
|
Loading…
Reference in New Issue