🚀 change module loading
This commit is contained in:
parent
7e4faed4a6
commit
309a57070c
26
README.md
26
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!
|
||||
|
|
|
@ -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);
|
||||
```
|
||||
|
||||
如果接下来你看到了这个运行结果,恭喜你!
|
||||
|
|
514
lib.nas
514
lib.nas
|
@ -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<y?x:y; }
|
||||
};
|
||||
|
||||
var unix={
|
||||
pipe: func(){return __pipe;},
|
||||
fork: func(){return __fork;},
|
||||
dup2: func(fd0,fd1){die("not supported yet");},
|
||||
exec: func(filename,argv,envp){die("not supported yet");},
|
||||
waitpid: func(pid,nohang=0){return __waitpid;},
|
||||
isdir: func(path){return !!bits.u32_and(io.stat(path)[2],0x4000);}, # S_IFDIR 0x4000
|
||||
isfile: func(path){return !!bits.u32_and(io.stat(path)[2],0x8000);}, # S_IFREG 0x8000
|
||||
opendir: func(path){return __opendir;},
|
||||
readdir: func(handle){return __readdir;},
|
||||
closedir: func(handle){return __closedir;},
|
||||
time: func(){return time(0);},
|
||||
sleep: func(secs){return __sleep(secs);},
|
||||
chdir: func(path){return __chdir(path);},
|
||||
environ: func(){return __environ();},
|
||||
getcwd: func(){return __getcwd();},
|
||||
getenv: func(envvar){return __getenv(envvar);},
|
||||
getpath: func(){return split(os.platform()=="windows"?";":":",unix.getenv("PATH"));}
|
||||
};
|
||||
|
||||
# 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.
|
||||
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);
|
||||
},
|
||||
# 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:
|
||||
# Caution: this may cause garbage collection process, be aware of the performance.
|
||||
dlcall: func(ptr,args...){return __dlcallv},
|
||||
# get dlcall function with limited parameter list
|
||||
limitcall: func(arg_size=0){
|
||||
if(arg_size==0){return func(ptr){return __dlcall};}
|
||||
else if(arg_size==1){return func(ptr,_0){return __dlcall};}
|
||||
else if(arg_size==2){return func(ptr,_0,_1){return __dlcall};}
|
||||
else if(arg_size==3){return func(ptr,_0,_1,_2){return __dlcall};}
|
||||
else if(arg_size==4){return func(ptr,_0,_1,_2,_3){return __dlcall};}
|
||||
else if(arg_size==5){return func(ptr,_0,_1,_2,_3,_4){return __dlcall};}
|
||||
else if(arg_size==6){return func(ptr,_0,_1,_2,_3,_4,_5){return __dlcall};}
|
||||
else if(arg_size==7){return func(ptr,_0,_1,_2,_3,_4,_5,_6){return __dlcall};}
|
||||
else if(arg_size==8){return func(ptr,_0,_1,_2,_3,_4,_5,_6,_7){return __dlcall};}
|
||||
else{return func(ptr,args...){return __dlcallv};}
|
||||
}
|
||||
};
|
||||
|
||||
# os is used to use or get some os-related info/functions.
|
||||
# windows/macOS/linux are supported.
|
||||
var os={
|
||||
# get a string that tell which os it runs on.
|
||||
platform: func(){return __platform;},
|
||||
time: func(){return __logtime; }
|
||||
};
|
||||
|
||||
# runtime gives us some functions that we could manage it manually.
|
||||
var runtime={
|
||||
# command line arguments
|
||||
argv: func(){return __sysargv;}
|
||||
};
|
||||
|
||||
# functions that not supported in this runtime:
|
||||
var bind=func(function,locals,outer_scope=nil){
|
||||
die("this runtime does not support bind");
|
||||
}
|
||||
|
||||
var call=func(function,args=nil,_me=nil,locals=nil,error=nil){
|
||||
die("this runtime does not support call");
|
||||
}
|
||||
|
||||
var caller=func(level=1){
|
||||
die("this runtime does not support caller");
|
||||
}
|
||||
|
||||
var closure=func(function,level=1){
|
||||
die("this runtime uses \"vm_upval\" instead of \"vm_hash\" as the closure");
|
||||
}
|
||||
|
||||
var compile=func(code,filename="<compile>"){
|
||||
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; }
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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)},
|
||||
|
|
|
@ -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);},
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 <get> 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 },
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue