From 309a57070c816af10ca8556ee84fb9523b927096 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Tue, 15 Nov 2022 21:23:34 +0800 Subject: [PATCH] :rocket: change module loading --- README.md | 26 ++- doc/README_zh.md | 27 +-- lib.nas | 514 ------------------------------------------- module/fib.cpp | 15 +- module/keyboard.cpp | 18 +- module/libfib.nas | 4 +- module/libkey.nas | 6 +- module/libmat.nas | 42 ++-- module/libsock.nas | 24 +- module/matrix.cpp | 72 +++--- module/nasocket.cpp | 45 ++-- nasal_builtin.h | 36 ++- nasal_gc.h | 6 +- stl/lib.nas | 4 +- test/module_test.nas | 8 +- 15 files changed, 154 insertions(+), 693 deletions(-) delete mode 100644 lib.nas diff --git a/README.md b/README.md index edffdb5..46b5506 100644 --- a/README.md +++ b/README.md @@ -631,16 +631,20 @@ var fib(var* args,usize size,gc* ngc){ return {vm_num,fibonaci(num.tonum())}; } +// then put function name and address into this table +// make sure the end of the table is {nullptr,nullptr} +mod_func func_tbl[]={ + {"fib",fib}, + {nullptr,nullptr} +}; + // must write this function, this will help nasal to // get the function pointer by name // the reason why using this way to get function pointer // is because `var` has constructors, which is not compatiable in C // so "extern "C" var fib" may get compilation warnings -extern "C" mod get(const char* n){ - string name=n; - if(name=="fib") - return fib; - return nullptr; +extern "C" mod_func get(){ + return func_tbl; } ``` @@ -664,15 +668,13 @@ Then we write a test nasal file to run this fib function, using `os.platform()` ```javascript var dlhandle=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); -var fib=dylib.dlsym(dlhandle,"fib"); +var fib=dlhandle.fib; for(var i=1;i<30;i+=1) println(dylib.dlcall(fib,i)); -dylib.dlclose(dlhandle); +dylib.dlclose(dlhandle.lib); ``` -`dylib.dlopen` is used to load dynamic library. - -`dylib.dlsym` is used to get the function address. +`dylib.dlopen` is used to load dynamic library and get the function address. `dylib.dlcall` is used to call the function, the first argument is the function address, make sure this argument is `vm_obj` and `type=obj_extern`. @@ -682,11 +684,11 @@ dylib.dlclose(dlhandle); ```javascript var dlhandle=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); -var fib=dylib.dlsym(dlhandle,"fib"); +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) println(invoke(fib,i)); -dylib.dlclose(dlhandle); +dylib.dlclose(dlhandle.lib); ``` If get this, Congratulations! diff --git a/doc/README_zh.md b/doc/README_zh.md index 4a4624c..249d828 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -604,15 +604,18 @@ var fib(var* args,usize size,gc* ngc){ return {vm_num,fibonaci(num.tonum())}; } +// 然后将函数名字和函数地址放到一个表里,一定要记住表尾是{nullptr,nullptr} +mod_func func_tbl[]={ + {"fib",fib}, + {nullptr,nullptr} +}; + // 必须实现这个函数, 这样nasal可以通过字符串名字获得函数指针 // 之所以用这种方式来获取函数指针, 是因为`var`是有构造函数的 // 有构造函数的类型作为返回值, 和C是不兼容的, 这导致 // 类似 "extern "C" var fib" 的写法会得到编译错误 -extern "C" mod get(const char* n){ - string name=n; - if(name=="fib") - return fib; - return nullptr; +extern "C" mod_func get(){ + return func_tbl; } ``` @@ -637,15 +640,13 @@ Windows(`.dll`): ```javascript var dlhandle=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); -var fib=dylib.dlsym(dlhandle,"fib"); +var fib=dlhandle.fib; for(var i=1;i<30;i+=1) println(dylib.dlcall(fib,i)); -dylib.dlclose(dlhandle); +dylib.dlclose(dlhandle.lib); ``` -`dylib.dlopen`用于加载动态库。 - -`dylib.dlsym`通过符号从动态库中获得函数地址。 +`dylib.dlopen`用于加载动态库并从动态库中获得函数地址。 `dylib.dlcall`用于调用函数,第一个参数是动态库函数的地址,这是个特殊类型,一定要保证这个参数是`vm_obj`类型并且`type=obj_extern`。 @@ -655,11 +656,11 @@ dylib.dlclose(dlhandle); ```javascript var dlhandle=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); -var fib=dylib.dlsym(dlhandle,"fib"); -var invoke=dylib.limitcall(1); # 这说明我们要调用的函数只有一个参数 +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) println(invoke(fib,i)); -dylib.dlclose(dlhandle); +dylib.dlclose(dlhandle.lib); ``` 如果接下来你看到了这个运行结果,恭喜你! diff --git a/lib.nas b/lib.nas deleted file mode 100644 index 295d964..0000000 --- a/lib.nas +++ /dev/null @@ -1,514 +0,0 @@ -# lib.nas -# 2019 ValKmjolnir - -# print is used to print all things in nasal, try and see how it works. -# this function uses std::cout to output logs. -var print=func(elems...){ - return __print(elems); -} - -# append is used to add values into a vector. -var append=func(vec,elems...){ - return __append(vec,elems); -} - -# setsize is used to change the size of vector. -# if the size is larger than before, -# this function will fill vm_nil into uninitialized space. -var setsize=func(vec,size){ - return __setsize(vec,size); -} - -# system has the same use in C. -var system=func(str){ - return __system(str); -} - -# input uses std::cin and returns what we input. -var input=func(end=nil){ - return __input(end); -} - -# split a string by separator for example: -# split("ll","hello world") -> ["he","o world"] -# this function will return a vector. -var split=func(separator,str){ - return __split(separator,str); -} - -# rand has the same function as the rand in C -# if seed is nil, it will return the random number. -# if seed is not nil, it will be initialized by this seed. -var rand=func(seed=nil){ - return __rand(seed); -} - -# id will return the pointer of an gc-object. -# if this object is not managed by gc, it will return 0. -var id=func(object){ - return __id(object); -} - -# int will get the integer of input number/string. -# but carefully use it, because int has range between -2147483648~2147483647 -var int=func(val){ - return __int(val); -} - -# floor will get the integral number of input argument -# which is less than or equal to this argument -var floor=func(val){ - return __floor(val); -} - -# exit using std::exit -var exit=func(val=-1){ - return __exit(val); -} - -# abort using std::abort -var abort=func(){ - __abort(); -} - -# abs gets absolute number. -var abs=func(n){ - return n>0?n:-n; -} - -# num will change all the other types into number. -# mostly used to change a numerable string. -var num=func(val){ - return __num(val); -} - -# pop used to pop the last element in a vector. -# this function will return the value that poped if vector has element(s). -# if the vector is empty, it will return nil. -var pop=func(vec){ - return __pop(vec); -} - -# str is used to change number into string. -var str=func(num){ - return __str(num); -} - -# size can get the size of a string/vector/hashmap. -# in fact it can also get the size of number, and the result is the number itself. -# so don't do useless things, though it really works. -var size=func(object){ - return __size(object); -} - -# contains is used to check if a key exists in a hashmap/dict. -var contains=func(hash,key){ - return __contains(hash,key); -} - -# delete is used to delete a pair in a hashmap/dict by key. -var delete=func(hash,key){ - return __delete(hash,key); -} - -# keys is used to get all keys in a hashmap/dict. -# this function will return a vector. -var keys=func(hash){ - return __keys(hash); -} - -# time has the same function in C. -var time=func(begin){ - return __time(begin); -} -var systime=func(){ - return time(0); -} - -# die is a special native function. -# use it at where you want the program to crash immediately. -var die=func(str){ - return __die(str); -} - -# find will give the first position of the needle in haystack -var find=func(needle,haystack){ - return __find(needle,haystack); -} - -# typeof is used to get the type of an object. -# this function returns a string. -var typeof=func(object){ - return __type(object); -} - -# subvec is used to get part of a vector -var subvec=func(vec,begin,length=nil){ - return vec[begin:(length==nil?nil:begin+length-1)]; -} - -# substr will get the sub-string. -# it gets the string, the begin index and sub-string's length as arguments. -var substr=func(str,begin,len){ - return __substr(str,begin,len); -} - -# streq is used to compare if two strings are the same. -var streq=func(a,b){ - return __streq(a,b); -} - -# left is used to get the sub-string like substr. -# but the begin index is 0. -var left=func(str,len){ - return __left(str,len); -} - -# right i used to get the sub-string like substr. -# but the begin index is strlen-len. -var right=func(str,len){ - return __right(str,len); -} - -# cmp is used to compare two strings. -# normal string will not be correctly compared by operators < > <= >= -# because these operators will turn strings into numbers then compare. -var cmp=func(a,b){ - return __cmp(a,b); -} - -# chr is used to get the character by ascii-number. -# for example chr(65) -> 'A' -var chr=func(code){ - return __chr(code); -} - -# char will give you the real character of ascii-number -# instead of extend-ascii when number between 128~256 -var char=func(code){ - return __char(code); -} - -# mut is used to change unmutable strings to mutable. -var mut=func(str){ - return str~""; -} - -# srand wraps up rand, using time(0) as the seed. -var srand=func(){ - rand(time(0)); - return 0; -} - -# values() gets all values in a hash. -var values=func(hash){ - return __values(hash); -} - -# println has the same function as print. -# but it will output a '\n' after using print. -var println=func(elems...){ - return __println(elems); -} - -var isfunc=func(f){ - return typeof(f)=="func"; -} - -var isghost=func(g){ - die("this runtime has no ghost object"); - return 0; -} - -var ishash=func(h){ - return typeof(h)=="hash"; -} - -var isint=func(x){ - return x==floor(x); -} - -var isnum=func(x){ - return typeof(x)=="num" or !math.isnan(num(x)); -} - -var isscalar=func(s){ - var t=typeof(s); - return (t=="num" or t=="str")?1:0; -} - -var isstr=func(s){ - return typeof(s)=="str"; -} - -var isvec=func(v){ - return typeof(v)=="vec"; -} - - -# get the index of val in the vec -var vecindex=func(vec,val){ - forindex(var i;vec) - if(val==vec[i]) - return i; - return nil; -} - -# check if the object is an instance of the class -var isa=func(object,class){ - if(!contains(object,"parents") or typeof(object.parents)!="vec") - return 0; - foreach(var elem;object.parents) - if(elem==class) - return 1; - return 0; -} - -# assert aborts when condition is not true -var assert=func(condition,message="assertion failed!"){ - if(condition) - return 1; - die(message); -} - -# get time stamp, this will return a timestamp object -var maketimestamp=func(){ - var t=0; - return { - stamp:func(){t=__millisec();}, - elapsedMSec:func(){return __millisec()-t;}, - elapsedUSec:func(){return (__millisec()-t)*1000;} - }; -} - -# md5 -var md5=func(str){ - return __md5(str); -} - -var io={ - SEEK_SET:0, - SEEK_CUR:1, - SEEK_END:2, - # get content of a file by filename. returns a string. - fin: func(filename){return __fin(filename);}, - # input a string as the content of a file. - fout: func(filename,str){return __fout(filename,str);}, - # use C access - exists:func(filename){return __exists(filename);}, - # same as C fopen. open file and get the FILE*. - open: func(filename,mode="r"){return __open(filename,mode);}, - # same as C fclose. close file by FILE*. - close: func(filehandle){return __close(filehandle);}, - # same as C fread. read file by FILE*. - # caution: buf must be a mutable string.use mut("") to get an empty mutable string. - read: func(filehandle,buf,len){return __read(filehandle,buf,len);}, - # same as C fwrite. write file by FILE*. - write: func(filehandle,str){return __write(filehandle,str);}, - # same as C fseek. seek place by FILE*. - seek: func(filehandle,pos,whence){return __seek(filehandle,pos,whence);}, - # same as C ftell. - tell: func(filehandle){return __tell(filehandle);}, - # read file by lines. use FILE*. - # get nil if EOF - readln:func(filehandle){return __readln(filehandle);}, - # same as C stat. - stat: func(filename){return __stat(filename);}, - # same as C feof. check if FILE* gets the end of file(EOF). - eof: func(filehandle){return __eof(filehandle);} -}; - -# get file status. using data from io.stat -var fstat=func(filename){ - var s=io.stat(filename); - return { - st_dev: s[0], - st_ino: s[1], - st_mode: s[2], - st_nlink:s[3], - st_uid: s[4], - st_gid: s[5], - st_rdev: s[6], - st_size: s[7], - st_atime:s[8], - st_mtime:s[9], - st_ctime:s[10] - }; -} - -# functions that do bitwise calculation. -# carefully use it, all the calculations are based on integer. -var bits={ - # i32 xor - i32_xor: func(a,b){return __i32xor(a,b); }, - # i32 and - i32_and: func(a,b){return __i32and(a,b); }, - # i32 or - i32_or: func(a,b){return __i32or(a,b); }, - # i32 nand - i32_nand:func(a,b){return __i32nand(a,b);}, - # i32 not - i32_not: func(a) {return __i32not(a); }, - # u32 xor - u32_xor: func(a,b){return __u32xor(a,b); }, - # u32 and - u32_and: func(a,b){return __u32and(a,b); }, - # u32 or - u32_or: func(a,b){return __u32or(a,b); }, - # u32 nand - u32_nand:func(a,b){return __u32nand(a,b);}, - # u32 not - u32_not: func(a) {return __u32not(a); }, - - # get bit data from a special string. for example: - # bits.fld(s,0,3); - # if s stores 10100010(162) - # will get 101(5). - fld: func(str,startbit,len){return __fld;}, - # get sign-extended data from a special string. for example: - # bits.sfld(s,0,3); - # if s stores 10100010(162) - # will get 101(5) then this will be signed extended to - # 11111101(-3). - sfld: func(str,startbit,len){return __sfld;}, - # set value into a special string to store it. little-endian, for example: - # bits.setfld(s,0,8,69); - # set 01000101(69) to string will get this: - # 10100010(162) - # so s[0]=162. - setfld: func(str,startbit,len,val){return __setfld;}, - # get a special string filled by '\0' to use in setfld. - buf: func(len){return __buf;} -}; - -# mostly used math functions and special constants, you know. -var math={ - e: 2.7182818284590452354, - pi: 3.14159265358979323846264338327950288, - D2R: 2.7182818284590452354/180, - R2D: 180/2.7182818284590452354, - inf: 1/0, - nan: 0/0, - abs: func(x) {return x>0?x:-x; }, - floor: func(x) {return __floor(x); }, - pow: func(x,y){return __pow(x,y); }, - sin: func(x) {return __sin(x); }, - cos: func(x) {return __cos(x); }, - tan: func(x) {return __tan(x); }, - exp: func(x) {return __exp(x); }, - lg: func(x) {return __lg(x); }, - ln: func(x) {return __ln(x); }, - sqrt: func(x) {return __sqrt(x); }, - atan2: func(x,y){return __atan2(x,y);}, - isnan: func(x) {return __isnan(x); }, - max: func(x,y){return x>y?x:y; }, - min: func(x,y){return x"){ - die("this runtime uses static code generator"); -} - -var coroutine={ - create: func(function){return __cocreate;}, - resume: func(co) {return __coresume;}, - yield: func(args...) {return __coyield; }, - status: func(co) {return __costatus;}, - running:func() {return __corun; } -}; diff --git a/module/fib.cpp b/module/fib.cpp index c4a3771..c99b5ff 100644 --- a/module/fib.cpp +++ b/module/fib.cpp @@ -29,11 +29,12 @@ var quick_fib(var* args,usize size,gc* ngc){ return {vm_num,res}; } -extern "C" mod get(const char* n){ - string name=n; - if(name=="fib") - return fib; - else if(name=="quick_fib") - return quick_fib; - return nullptr; +mod_func func_tbl[]={ + {"fib",fib}, + {"quick_fib",quick_fib}, + {nullptr, nullptr}, +}; + +extern "C" mod_func* get(){ + return func_tbl; } \ No newline at end of file diff --git a/module/keyboard.cpp b/module/keyboard.cpp index 280a743..9f95dba 100644 --- a/module/keyboard.cpp +++ b/module/keyboard.cpp @@ -83,13 +83,13 @@ var nas_noblock(var* args,usize size,gc* ngc){ return nil; } -extern "C" mod get(const char* n){ - string name=n; - if(name=="nas_getch") - return nas_getch; - else if(name=="nas_kbhit") - return nas_kbhit; - else if(name=="nas_noblock") - return nas_noblock; - return nullptr; +mod_func func_tbl[]={ + {"nas_getch",nas_getch}, + {"nas_kbhit",nas_kbhit}, + {"nas_noblock",nas_noblock}, + {nullptr,nullptr} +}; + +extern "C" mod_func* get(){ + return func_tbl; } \ No newline at end of file diff --git a/module/libfib.nas b/module/libfib.nas index 064bcf4..b852ec0 100644 --- a/module/libfib.nas +++ b/module/libfib.nas @@ -1,7 +1,7 @@ var libfib=func(){ var dl=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); - var fib=dylib.dlsym(dl,"fib"); - var qfib=dylib.dlsym(dl,"quick_fib"); + var fib=dl.fib; + var qfib=dl.quick_fib; var call=dylib.limitcall(1); return { fib: func(x){return call(fib,x)}, diff --git a/module/libkey.nas b/module/libkey.nas index f08073e..9079108 100644 --- a/module/libkey.nas +++ b/module/libkey.nas @@ -1,8 +1,8 @@ var libkey=func(){ var lib=dylib.dlopen("libkey"~(os.platform()=="windows"?".dll":".so")); - var kb=dylib.dlsym(lib,"nas_kbhit"); - var gt=dylib.dlsym(lib,"nas_getch"); - var nb=dylib.dlsym(lib,"nas_noblock"); + var kb=lib.nas_kbhit; + var gt=lib.nas_getch; + var nb=lib.nas_noblock; var call=dylib.limitcall(0); return { kbhit:func(){return call(kb);}, diff --git a/module/libmat.nas b/module/libmat.nas index e557551..64a1cbd 100644 --- a/module/libmat.nas +++ b/module/libmat.nas @@ -1,31 +1,31 @@ var libmat=func(){ var dl=dylib.dlopen("libmat."~(os.platform()=="windows"?"dll":"so")); - var vec2=dylib.dlsym(dl,"nas_vec2"); - var vec3=dylib.dlsym(dl,"nas_vec3"); + var vec2=dl.nas_vec2; + var vec3=dl.nas_vec3; var (vec2add,vec2sub,vec2mul,vec2div,vec2neg,vec2norm,vec2len,vec2dot)=( - dylib.dlsym(dl,"nas_vec2_add"), - dylib.dlsym(dl,"nas_vec2_sub"), - dylib.dlsym(dl,"nas_vec2_mult"), - dylib.dlsym(dl,"nas_vec2_div"), - dylib.dlsym(dl,"nas_vec2_neg"), - dylib.dlsym(dl,"nas_vec2_norm"), - dylib.dlsym(dl,"nas_vec2_len"), - dylib.dlsym(dl,"nas_vec2_dot") + dl.nas_vec2_add, + dl.nas_vec2_sub, + dl.nas_vec2_mult, + dl.nas_vec2_div, + dl.nas_vec2_neg, + dl.nas_vec2_norm, + dl.nas_vec2_len, + dl.nas_vec2_dot ); var (vec3add,vec3sub,vec3mul,vec3div,vec3neg,vec3norm,vec3len,vec3dot)=( - dylib.dlsym(dl,"nas_vec3_add"), - dylib.dlsym(dl,"nas_vec3_sub"), - dylib.dlsym(dl,"nas_vec3_mult"), - dylib.dlsym(dl,"nas_vec3_div"), - dylib.dlsym(dl,"nas_vec3_neg"), - dylib.dlsym(dl,"nas_vec3_norm"), - dylib.dlsym(dl,"nas_vec3_len"), - dylib.dlsym(dl,"nas_vec3_dot") + dl.nas_vec3_add, + dl.nas_vec3_sub, + dl.nas_vec3_mult, + dl.nas_vec3_div, + dl.nas_vec3_neg, + dl.nas_vec3_norm, + dl.nas_vec3_len, + dl.nas_vec3_dot ); var (rotate_x,rotate_y,rotate_z)=( - dylib.dlsym(dl,"nas_rotate_x"), - dylib.dlsym(dl,"nas_rotate_y"), - dylib.dlsym(dl,"nas_rotate_z") + dl.nas_rotate_x, + dl.nas_rotate_y, + dl.nas_rotate_z ); var (invoke_i,invoke_ii,invoke_iii)=( dylib.limitcall(1), diff --git a/module/libsock.nas b/module/libsock.nas index 2c9d28e..cafa7bb 100644 --- a/module/libsock.nas +++ b/module/libsock.nas @@ -1,18 +1,18 @@ var socket=func(){ var lib=dylib.dlopen("libnasock"~(os.platform()=="windows"?".dll":".so")); - var sock=dylib.dlsym(lib,"nas_socket"); - var closesocket=dylib.dlsym(lib,"nas_closesocket"); - var shutdown=dylib.dlsym(lib,"nas_shutdown"); - var bind=dylib.dlsym(lib,"nas_bind"); - var listen=dylib.dlsym(lib,"nas_listen"); - var connect=dylib.dlsym(lib,"nas_connect"); - var accept=dylib.dlsym(lib,"nas_accept"); - var send=dylib.dlsym(lib,"nas_send"); - var sendto=dylib.dlsym(lib,"nas_sendto"); - var recv=dylib.dlsym(lib,"nas_recv"); - var recvfrom=dylib.dlsym(lib,"nas_recvfrom"); - var errno=dylib.dlsym(lib,"nas_errno"); + var sock=lib.nas_socket; + var closesocket=lib.nas_closesocket; + var shutdown=lib.nas_shutdown; + var bind=lib.nas_bind; + var listen=lib.nas_listen; + var connect=lib.nas_connect; + var accept=lib.nas_accept; + var send=lib.nas_send; + var sendto=lib.nas_sendto; + var recv=lib.nas_recv; + var recvfrom=lib.nas_recvfrom; + var errno=lib.nas_errno; var (invoke,invoke_i,invoke_ii,invoke_iii,invoke_iiii,invoke_iiiii)=( dylib.limitcall(0), diff --git a/module/matrix.cpp b/module/matrix.cpp index e3511ec..a0bcdc1 100644 --- a/module/matrix.cpp +++ b/module/matrix.cpp @@ -266,49 +266,31 @@ var nas_vec3_dot(var* args,usize size,gc* ngc){ return {vm_num,v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()+v0[2].num()*v1[2].num()}; } -extern "C" mod get(const char* n){ - string name=n; - if(name=="nas_vec2") - return nas_vec2; - else if(name=="nas_vec2_add") - return nas_vec2_add; - else if(name=="nas_vec2_sub") - return nas_vec2_sub; - else if(name=="nas_vec2_mult") - return nas_vec2_mult; - else if(name=="nas_vec2_div") - return nas_vec2_div; - else if(name=="nas_vec2_neg") - return nas_vec2_neg; - else if(name=="nas_vec2_norm") - return nas_vec2_norm; - else if(name=="nas_vec2_len") - return nas_vec2_len; - else if(name=="nas_vec2_dot") - return nas_vec2_dot; - else if(name=="nas_vec3") - return nas_vec3; - else if(name=="nas_vec3_add") - return nas_vec3_add; - else if(name=="nas_vec3_sub") - return nas_vec3_sub; - else if(name=="nas_vec3_mult") - return nas_vec3_mult; - else if(name=="nas_vec3_div") - return nas_vec3_div; - else if(name=="nas_vec3_neg") - return nas_vec3_neg; - else if(name=="nas_vec3_norm") - return nas_vec3_norm; - else if(name=="nas_vec3_len") - return nas_vec3_len; - else if(name=="nas_rotate_x") - return nas_rotate_x; - else if(name=="nas_rotate_y") - return nas_rotate_y; - else if(name=="nas_rotate_z") - return nas_rotate_z; - else if(name=="nas_vec3_dot") - return nas_vec3_dot; - return nullptr; +mod_func func_tbl[]={ + {"nas_vec2",nas_vec2}, + {"nas_vec2_add",nas_vec2_add}, + {"nas_vec2_sub",nas_vec2_sub}, + {"nas_vec2_mult",nas_vec2_mult}, + {"nas_vec2_div",nas_vec2_div}, + {"nas_vec2_neg",nas_vec2_neg}, + {"nas_vec2_norm",nas_vec2_norm}, + {"nas_vec2_len",nas_vec2_len}, + {"nas_vec2_dot",nas_vec2_dot}, + {"nas_vec3",nas_vec3}, + {"nas_vec3_add",nas_vec3_add}, + {"nas_vec3_sub",nas_vec3_sub}, + {"nas_vec3_mult",nas_vec3_mult}, + {"nas_vec3_div",nas_vec3_div}, + {"nas_vec3_neg",nas_vec3_neg}, + {"nas_vec3_norm",nas_vec3_norm}, + {"nas_vec3_len",nas_vec3_len}, + {"nas_rotate_x",nas_rotate_x}, + {"nas_rotate_y",nas_rotate_y}, + {"nas_rotate_z",nas_rotate_z}, + {"nas_vec3_dot",nas_vec3_dot}, + {nullptr,nullptr} +}; + +extern "C" mod_func* get(){ + return func_tbl; } \ No newline at end of file diff --git a/module/nasocket.cpp b/module/nasocket.cpp index 5c4a408..82bbc7a 100644 --- a/module/nasocket.cpp +++ b/module/nasocket.cpp @@ -187,31 +187,22 @@ var nas_errno(var* args,usize size,gc* ngc){ return ngc->newstr(strerror(errno)); } -extern "C" mod get(const char* n){ - string name=n; - if(name=="nas_socket") - return nas_socket; - else if(name=="nas_closesocket") - return nas_closesocket; - else if(name=="nas_shutdown") - return nas_shutdown; - else if(name=="nas_bind") - return nas_bind; - else if(name=="nas_listen") - return nas_listen; - else if(name=="nas_connect") - return nas_connect; - else if(name=="nas_accept") - return nas_accept; - else if(name=="nas_send") - return nas_send; - else if(name=="nas_sendto") - return nas_sendto; - else if(name=="nas_recv") - return nas_recv; - else if(name=="nas_recvfrom") - return nas_recvfrom; - else if(name=="nas_errno") - return nas_errno; - return nullptr; +mod_func func_tbl[]={ + {"nas_socket",nas_socket}, + {"nas_closesocket",nas_closesocket}, + {"nas_shutdown",nas_shutdown}, + {"nas_bind",nas_bind}, + {"nas_listen",nas_listen}, + {"nas_connect",nas_connect}, + {"nas_accept",nas_accept}, + {"nas_send",nas_send}, + {"nas_sendto",nas_sendto}, + {"nas_recv",nas_recv}, + {"nas_recvfrom",nas_recvfrom}, + {"nas_errno",nas_errno}, + {nullptr,nullptr} +}; + +extern "C" mod_func* get(){ + return func_tbl; } \ No newline at end of file diff --git a/nasal_builtin.h b/nasal_builtin.h index 9c7aa48..e97f533 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -930,33 +930,30 @@ var builtin_dlopen(var* local,gc& ngc) #endif if(!ptr) return nas_err("dlopen","cannot open dynamic lib <"+dlname.str()+">"); - var ret=ngc.alloc(vm_obj); - ret.obj().set(nas_obj::dylib,ptr); - return ret; -} + var ret=ngc.temp=ngc.alloc(vm_hash); + var lib=ngc.alloc(vm_obj); + lib.obj().set(nas_obj::dylib,ptr); + ret.hash().elems["lib"]=lib; -var builtin_dlsym(var* local,gc& ngc) -{ - var lib=local[1]; - var sym=local[2]; - if(!lib.objchk(nas_obj::dylib)) - return nas_err("dlsym","\"lib\" is not a valid dynamic lib"); - if(sym.type!=vm_str) - return nas_err("dlsym","\"sym\" must be string"); - // "get" function #ifdef _WIN32 void* func=(void*)GetProcAddress((HMODULE)lib.obj().ptr,"get"); #else void* func=dlsym(lib.obj().ptr,"get"); #endif if(!func) - return nas_err("dlsym","cannot find get function"); + return nas_err("dlopen","cannot find function"); // get function pointer by name - void* ptr=(void*)((getptr)func)(sym.str().c_str()); - if(!ptr) - return nas_err("dlsym","cannot find function <"+sym.str()+">"); - var ret=ngc.alloc(vm_obj); - ret.obj().set(nas_obj::faddr,ptr); + mod_func* tbl=(mod_func*)((getptr)func)(); + if(!tbl) + return nas_err("dlopen","failed to get module functions"); + for(u32 i=0;tbl[i].name;++i){ + void* p=(void*)tbl[i].fd; + var tmp=ngc.alloc(vm_obj); + tmp.obj().set(nas_obj::faddr,p); + ret.hash().elems[tbl[i].name]=tmp; + } + + ngc.temp=nil; return ret; } @@ -1295,7 +1292,6 @@ struct {"__getcwd", builtin_getcwd }, {"__getenv", builtin_getenv }, {"__dlopen", builtin_dlopen }, - {"__dlsym", builtin_dlsym }, {"__dlclose", builtin_dlclose }, {"__dlcallv", builtin_dlcallv }, {"__dlcall", builtin_dlcall }, diff --git a/nasal_gc.h b/nasal_gc.h index d127f64..671fc2d 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -778,4 +778,8 @@ var nas_err(const string& err_f,const string& info) } typedef var (*mod)(var*,usize,gc*); // module function type -typedef mod (*getptr)(const char*); // module function "get" type +typedef struct { + const char* name; + mod fd; +} mod_func; // module function stores in tables with this type, end with {nullptr,nullptr} +typedef mod_func* (*getptr)(); // module function "get" type diff --git a/stl/lib.nas b/stl/lib.nas index 295d964..f91941b 100644 --- a/stl/lib.nas +++ b/stl/lib.nas @@ -428,7 +428,7 @@ var unix={ # dylib is the core hashmap for developers to load their own library. # for safe using dynamic library, you could use 'module' in stl/module.nas var dylib={ - # open dynamic lib. + # open dynamic lib. return a hash including dl pointer and function pointers dlopen: func(libname){ # find dynamic lib from local dir first libname=(os.platform()=="windows"?".\\":"./")~libname; @@ -448,8 +448,6 @@ var dylib={ } return __dlopen(libname); }, - # load symbol from an open dynamic lib. - dlsym: func(lib,sym){return __dlsym; }, # close dynamic lib, this operation will make all the symbols loaded from it invalid. dlclose: func(lib){return __dlclose; }, # call the loaded symbol, with infinite parameters: diff --git a/test/module_test.nas b/test/module_test.nas index aee3b81..7b84f4d 100644 --- a/test/module_test.nas +++ b/test/module_test.nas @@ -5,8 +5,8 @@ var libfib=func(){ open:func(){ if(dd==nil){ dd=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); - fib=dylib.dlsym(dd,"fib"); - qfib=dylib.dlsym(dd,"quick_fib"); + fib=dd.fib; + qfib=dd.quick_fib; }else{ println("[info ] already loaded."); } @@ -16,7 +16,7 @@ var libfib=func(){ println("[error ] already closed."); return; } - dylib.dlclose(dd); + dylib.dlclose(dd.lib); (dd,fib,qfib)=(nil,nil,nil); }, fib:func(x){ @@ -51,7 +51,7 @@ libfib.close(); var speed_test=func(){ var d=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); - var fd=dylib.dlsym(d,"quick_fib"); + var fd=d.quick_fib; var vec_call=dylib.dlcall; var invoke=dylib.limitcall(1);