🚀 change module function parameter format to avoid warnings

This commit is contained in:
ValKmjolnir 2022-10-24 01:12:25 +08:00
parent 3ef8effe9a
commit c705b75513
11 changed files with 199 additions and 99 deletions

View File

@ -615,9 +615,8 @@ double fibonaci(double x){
return x;
return fibonaci(x-1)+fibonaci(x-2);
}
// remember to use extern "C",
// so you could search the symbol quickly
extern "C" var fib(std::vector<var>& args,gc& ngc){
// module functions' parameter list example
var fib(var* args,usize size,gc* ngc){
// the arguments are generated into a vm_vec: args
// get values from the vector that must be used here
var num=args[0];
@ -627,10 +626,22 @@ extern "C" var fib(std::vector<var>& args,gc& ngc){
if(num.type!=vm_num)
return nas_err("extern_fib","\"num\" must be number");
// ok, you must know that vm_num now is not managed by gc
// if want to return a gc object, use ngc.alloc(type)
// if want to return a gc object, use ngc->alloc(type)
// usage of gc is the same as adding a native function
return {vm_num,fibonaci(num.tonum())};
}
// 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;
}
```
Next, compile this `fib.cpp` into dynamic lib.

View File

@ -590,19 +590,30 @@ double fibonaci(double x){
return x;
return fibonaci(x-1)+fibonaci(x-2);
}
// 记得用extern "C"
// 这样找符号会更加快速便捷不要在意编译时的warning
extern "C" var fib(std::vector<var>& args,gc& ngc){
// 传参会被送到一个vm_vec类型中送过来而不是上文中那种指针直接指向局部作用域
// 模块函数的参数列表一律以这个为准
var fib(var* args,usize size,gc* ngc){
// 传参会给予一个var指针指向一个vm_vec的data()
var num=args[0];
// 如果你想让这个函数有更强的稳定性,那么一定要进行合法性检查
// builtin_err会输出错误信息并返回错误类型让虚拟机终止执行
// nas_err会输出错误信息并返回错误类型让虚拟机终止执行
if(num.type!=vm_num)
return nas_err("extern_fib","\"num\" must be number");
// vm_num作为普通的数字类型不是内存管理的对象所以无需申请
// 如果需要返回内存管理的对象请使用ngc.alloc(type)
// 如果需要返回内存管理的对象请使用ngc->alloc(type)
return {vm_num,fibonaci(num.tonum())};
}
// 必须实现这个函数, 这样nasal可以通过字符串名字获得函数指针
// 之所以用这种方式来获取函数指针, 是因为`var`是有构造函数的
// 有构造函数的类型作为返回值, 和C是不兼容的, 这导致
// 类似 "extern "C" var fib" 的写法会得到编译错误
extern "C" mod get(const char* n){
string name=n;
if(name=="fib")
return fib;
return nullptr;
}
```
接着我们把`fib.cpp`编译成动态库。

View File

@ -6,18 +6,20 @@ double fibonaci(double x){
return x;
return fibonaci(x-1)+fibonaci(x-2);
}
extern "C" var fib(std::vector<var>& args,gc& ngc){
var fib(var* args,usize size,gc* ngc){
std::cout<<"[mod] this is the first test module of nasal\n";
if(!args.size())
if(!size)
return nas_err("fib","lack arguments");
var num=args[0];
if(num.type!=vm_num)
return nas_err("extern_fib","\"num\" must be number");
return {vm_num,fibonaci(num.tonum())};
}
extern "C" var quick_fib(std::vector<var>& args,gc& ngc){
var quick_fib(var* args,usize size,gc* ngc){
std::cout<<"[mod] this is the first test module of nasal\n";
if(!args.size())
if(!size)
return nas_err("fib","lack arguments");
var num=args[0];
if(num.type!=vm_num)
@ -31,4 +33,13 @@ extern "C" var quick_fib(std::vector<var>& args,gc& ngc){
b=res;
}
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;
}

View File

@ -71,14 +71,25 @@ public:
};
noecho_input this_window;
extern "C" var nas_getch(std::vector<var>& args,gc& ngc){
var nas_getch(var* args,usize size,gc* ngc){
return {vm_num,(double)this_window.noecho_getch()};
}
extern "C" var nas_kbhit(std::vector<var>& args,gc& ngc){
var nas_kbhit(var* args,usize size,gc* ngc){
return {vm_num,(double)this_window.noecho_kbhit()};
}
extern "C" var nas_noblock(std::vector<var>& args,gc& ngc){
var nas_noblock(var* args,usize size,gc* ngc){
if(this_window.noecho_kbhit())
return {vm_num,(double)this_window.noecho_getch()};
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;
}

View File

@ -3,36 +3,41 @@
STD=14
libfib.so: fib.cpp
$(CXX) -std=c++$(STD) -c -O3 fib.cpp -fPIC -o fib.o
$(CXX) -shared -o libfib.so fib.o
rm fib.o
@ echo "[build] libfib.so"
@ $(CXX) -std=c++$(STD) -c -O3 fib.cpp -fPIC -o fib.o
@ $(CXX) -shared -o libfib.so fib.o
@ rm fib.o
libfib.dll: fib.cpp
$(CXX) -std=c++$(STD) -c -O3 fib.cpp -fPIC -o fib.o
$(CXX) -shared -o libfib.dll fib.o
del fib.o
@ echo [build] libfib.dll
@ $(CXX) -std=c++$(STD) -c -O3 fib.cpp -fPIC -o fib.o
@ $(CXX) -shared -o libfib.dll fib.o
@ del fib.o
libkey.so: keyboard.cpp
$(CXX) -std=c++$(STD) -c -O3 keyboard.cpp -fPIC -o keyboard.o
$(CXX) -shared -o libkey.so keyboard.o
rm keyboard.o
@ echo "[build] libkey.so"
@ $(CXX) -std=c++$(STD) -c -O3 keyboard.cpp -fPIC -o keyboard.o
@ $(CXX) -shared -o libkey.so keyboard.o
@ rm keyboard.o
libkey.dll: keyboard.cpp
$(CXX) -std=c++$(STD) -c -O3 keyboard.cpp -fPIC -o keyboard.o -static
$(CXX) -shared -o libkey.dll keyboard.o -static
del keyboard.o
@ echo [build] libkey.dll
@ $(CXX) -std=c++$(STD) -c -O3 keyboard.cpp -fPIC -o keyboard.o -static
@ $(CXX) -shared -o libkey.dll keyboard.o -static
@ del keyboard.o
libnasock.so: nasocket.cpp
$(CXX) -std=c++$(STD) -c -O3 nasocket.cpp -fPIC -o nasocket.o
$(CXX) -shared -o libnasock.so nasocket.o
rm nasocket.o
@ echo "[build] libnasock.so"
@ $(CXX) -std=c++$(STD) -c -O3 nasocket.cpp -fPIC -o nasocket.o
@ $(CXX) -shared -o libnasock.so nasocket.o
@ rm nasocket.o
libnasock.dll: nasocket.cpp
$(CXX) -std=c++$(STD) -c -O3 nasocket.cpp -fPIC -o nasocket.o -lwsock32 -static
$(CXX) -shared -o libnasock.dll nasocket.o -lwsock32 -static
del nasocket.o
@ echo [build] libnasock.dll
@ $(CXX) -std=c++$(STD) -c -O3 nasocket.cpp -fPIC -o nasocket.o -lwsock32 -static
@ $(CXX) -shared -o libnasock.dll nasocket.o -lwsock32 -static
@ del nasocket.o
clean:
-@ rm *.so *.dll *.dylib
@ echo "done"
all: libfib.so libkey.so libnasock.so
@ echo "build done"
@ echo "[build] done"
mingw-all: libfib.dll libkey.dll libnasock.dll
@ echo build done
@ echo [build] done

View File

@ -25,14 +25,14 @@ static WSAmanager win;
#include <netinet/in.h>
#endif
extern "C" var nas_socket(std::vector<var>& args,gc& ngc){
var nas_socket(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num)
return nas_err("socket","\"af\", \"type\", \"protocol\" should be number");
int sd=socket(args[0].num(),args[1].num(),args[2].num());
return {vm_num,(double)sd};
}
extern "C" var nas_closesocket(std::vector<var>& args,gc& ngc){
var nas_closesocket(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("closesocket","\"\" should be number");
#ifdef _WIN32
@ -42,7 +42,7 @@ extern "C" var nas_closesocket(std::vector<var>& args,gc& ngc){
#endif
}
extern "C" var nas_shutdown(std::vector<var>& args,gc& ngc){
var nas_shutdown(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("shutdown","\"sd\" must be a number");
if(args[1].type!=vm_num)
@ -50,7 +50,7 @@ extern "C" var nas_shutdown(std::vector<var>& args,gc& ngc){
return {vm_num,(double)shutdown(args[0].num(),args[1].num())};
}
extern "C" var nas_bind(std::vector<var>& args,gc& ngc){
var nas_bind(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("bind","\"sd\" muse be a number");
if(args[1].type!=vm_str)
@ -65,7 +65,7 @@ extern "C" var nas_bind(std::vector<var>& args,gc& ngc){
return {vm_num,(double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))};
}
extern "C" var nas_listen(std::vector<var>& args,gc& ngc){
var nas_listen(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("listen","\"sd\" must be a number");
if(args[1].type!=vm_num)
@ -73,7 +73,7 @@ extern "C" var nas_listen(std::vector<var>& args,gc& ngc){
return{vm_num,(double)listen(args[0].num(),args[1].num())};
}
extern "C" var nas_connect(std::vector<var>& args,gc& ngc){
var nas_connect(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("connect","\"sd\" must be a number");
if(args[1].type!=vm_str)
@ -89,7 +89,7 @@ extern "C" var nas_connect(std::vector<var>& args,gc& ngc){
return {vm_num,(double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))};
}
extern "C" var nas_accept(std::vector<var>& args,gc& ngc){
var nas_accept(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("accept","\"sd\" must be a number");
sockaddr_in client;
@ -99,15 +99,15 @@ extern "C" var nas_accept(std::vector<var>& args,gc& ngc){
#else
int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen);
#endif
var res=ngc.temp=ngc.alloc(vm_hash);
var res=ngc->temp=ngc->alloc(vm_hash);
auto& hash=res.hash().elems;
hash["sd"]={vm_num,(double)client_sd};
hash["ip"]=ngc.newstr(inet_ntoa(client.sin_addr));
ngc.temp=nil;
hash["ip"]=ngc->newstr(inet_ntoa(client.sin_addr));
ngc->temp=nil;
return res;
}
extern "C" var nas_send(std::vector<var>& args,gc& ngc){
var nas_send(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("send","\"sd\" must be a number");
if(args[1].type!=vm_str)
@ -117,7 +117,7 @@ extern "C" var nas_send(std::vector<var>& args,gc& ngc){
return {vm_num,(double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num())};
}
extern "C" var nas_sendto(std::vector<var>& args,gc& ngc){
var nas_sendto(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("sendto","\"sd\" must be a number");
if(args[1].type!=vm_str)
@ -137,7 +137,7 @@ extern "C" var nas_sendto(std::vector<var>& args,gc& ngc){
return {vm_num,(double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in))};
}
extern "C" var nas_recv(std::vector<var>& args,gc& ngc){
var nas_recv(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("recv","\"sd\" must be a number");
if(args[1].type!=vm_num)
@ -146,17 +146,17 @@ extern "C" var nas_recv(std::vector<var>& args,gc& ngc){
return nas_err("recv","\"len\" out of range");
if(args[2].type!=vm_num)
return nas_err("recv","\"flags\" muse be a number");
var res=ngc.temp=ngc.alloc(vm_hash);
var res=ngc->temp=ngc->alloc(vm_hash);
auto& hash=res.hash().elems;
char* buf=new char[(int)args[1].num()];
hash["size"]={vm_num,(double)recv(args[0].num(),buf,args[1].num(),args[2].num())};
hash["str"]=ngc.newstr(buf);
hash["str"]=ngc->newstr(buf);
delete[] buf;
ngc.temp=nil;
ngc->temp=nil;
return res;
}
extern "C" var nas_recvfrom(std::vector<var>& args,gc& ngc){
var nas_recvfrom(var* args,usize size,gc* ngc){
if(args[0].type!=vm_num)
return nas_err("recvfrom","\"sd\" must be a number");
if(args[1].type!=vm_num)
@ -167,7 +167,7 @@ extern "C" var nas_recvfrom(std::vector<var>& args,gc& ngc){
return nas_err("recvfrom","\"flags\" muse be a number");
sockaddr_in addr;
int socklen=sizeof(sockaddr_in);
var res=ngc.temp=ngc.alloc(vm_hash);
var res=ngc->temp=ngc->alloc(vm_hash);
auto& hash=res.hash().elems;
char* buf=new char[(int)args[1].num()+1];
#ifdef _WIN32
@ -176,13 +176,42 @@ extern "C" var nas_recvfrom(std::vector<var>& args,gc& ngc){
hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen)};
#endif
buf[(int)hash["size"].num()]=0;
hash["str"]=ngc.newstr(buf);
hash["str"]=ngc->newstr(buf);
delete[] buf;
hash["fromip"]=ngc.newstr(inet_ntoa(addr.sin_addr));
ngc.temp=nil;
hash["fromip"]=ngc->newstr(inet_ntoa(addr.sin_addr));
ngc->temp=nil;
return res;
}
extern "C" var nas_errno(std::vector<var>& args,gc& ngc){
return ngc.newstr(strerror(errno));
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;
}

View File

@ -130,7 +130,7 @@ var builtin_split(var* local,gc& ngc)
// avoid being sweeped
var res=ngc.temp=ngc.alloc(vm_vec);
std::vector<var>& vec=res.vec().elems;
auto& vec=res.vec().elems;
if(!deli.length())
{
@ -850,7 +850,7 @@ var builtin_getenv(var* local,gc& ngc)
char* res=getenv(envvar.str().c_str());
return res?ngc.newstr(res):nil;
}
void obj_dylib_dtor(void* ptr)
void dylib_dtor(void* ptr)
{
#ifdef _WIN32
FreeLibrary((HMODULE)ptr);
@ -869,7 +869,7 @@ var builtin_dlopen(var* local,gc& ngc)
return nas_err("dlopen","malloc failed");
memset(str,0,sizeof(wchar_t)*dlname.str().size()+1);
mbstowcs(str,dlname.str().c_str(),dlname.str().size()+1);
void* ptr=LoadLibraryW(str);
void* ptr=LoadLibraryA(dlname.str().c_str());
delete []str;
#else
void* ptr=dlopen(dlname.str().c_str(),RTLD_LOCAL|RTLD_LAZY);
@ -877,7 +877,7 @@ var builtin_dlopen(var* local,gc& ngc)
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,obj_dylib_dtor);
ret.obj().set(nas_obj::dylib,ptr,dylib_dtor);
return ret;
}
var builtin_dlsym(var* local,gc& ngc)
@ -888,15 +888,20 @@ var builtin_dlsym(var* local,gc& ngc)
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,sym.str().c_str());
void* func=(void*)GetProcAddress((HMODULE)lib.obj().ptr,"get");
#else
void* func=dlsym(lib.obj().ptr,sym.str().c_str());
void* func=dlsym(lib.obj().ptr,"get");
#endif
if(!func)
return nas_err("dlsym","cannot find symbol \""+sym.str()+"\"");
return nas_err("dlsym","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,func);
ret.obj().set(nas_obj::faddr,ptr);
return ret;
}
var builtin_dlclose(var* local,gc& ngc)
@ -918,9 +923,8 @@ var builtin_dlcall(var* local,gc& ngc)
var args=local[2];
if(!fp.objchk(nas_obj::faddr))
return nas_err("dlcall","\"funcptr\" is not a valid function pointer");
typedef var (*externs)(std::vector<var>&,gc&);
externs func=(externs)fp.obj().ptr;
return func(args.vec().elems,ngc);
auto& vec=args.vec().elems;
return ((mod)fp.obj().ptr)(vec.data(),vec.size(),&ngc);
}
var builtin_platform(var* local,gc& ngc)

View File

@ -460,16 +460,18 @@ struct gc
} mctx;
/* runtime context */
u32& pc; // program counter
var*& localr;// local scope register
var*& memr; // used for mem_call
var& funcr; // function register
var& upvalr;// upvalue register
var*& canary;// avoid stackoverflow
var*& top; // stack top
var* stack; // stack pointer
nas_co* cort;// running coroutine
var temp; // temporary place used in builtin/module functions
u32& pc; // program counter
var*& localr; // local scope register
var*& memr; // used for mem_call
var& funcr; // function register
var& upvalr; // upvalue register
var*& canary; // avoid stackoverflow
var*& top; // stack top
var* stack; // stack pointer
nas_co* cort; // running coroutine
/* native function used */
var temp; // temporary place used in builtin/module functions
/* constants and memory pool */
std::vector<var> strs; // reserved address for const vm_str
@ -720,4 +722,8 @@ var nas_err(const string& err_f,const string& info)
std::cerr<<"[vm] "<<err_f<<": "<<info<<"\n";
return {vm_none};
}
typedef var (*mod)(var*,usize,gc*); // module function type
typedef mod (*getptr)(const char*); // module function "get" type
#endif

View File

@ -602,7 +602,7 @@ inline void vm::o_findex()
}
inline void vm::o_feach()
{
std::vector<var>& ref=top[-1].vec().elems;
auto& ref=top[-1].vec().elems;
if((usize)(++top[0].cnt())>=ref.size())
{
pc=imm[pc]-1;
@ -800,8 +800,8 @@ inline void vm::o_slc2()
{
var val2=(top--)[0];
var val1=(top--)[0];
std::vector<var>& ref=top[-1].vec().elems;
std::vector<var>& aim=top[0].vec().elems;
auto& ref=top[-1].vec().elems;
auto& aim=top[0].vec().elems;
u8 type1=val1.type,type2=val2.type;
i32 num1=val1.tonum();

View File

@ -5,7 +5,10 @@ var http=func(){
return {
establish:func(ip,port){
sd=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP);
socket.bind(sd,ip,port);
if(socket.bind(sd,ip,port)<0){
println("failed to bind socket "~sd~" at IP: "~ip~" port: "~port~".");
return;
}
socket.listen(sd,1);
println("[",os.time(),"] start server at [",ip,":",port,"]");
},
@ -40,7 +43,6 @@ var http=func(){
}();
http.establish("127.0.0.1",8080);
var highlight_style="
<style>
body{

View File

@ -16,14 +16,20 @@ var cpu_stat=func(){
};
return cpu;
}
var cpu_occupation=func(){
var cpu0=cpu_stat();
unix.sleep(0.5);
var cpu1=cpu_stat();
var t0=cpu0.user+cpu0.nice+cpu0.system+cpu0.idle+cpu0.iowait+cpu0.irq+cpu0.softirq;
var t1=cpu1.user+cpu1.nice+cpu1.system+cpu1.idle+cpu1.iowait+cpu1.irq+cpu1.softirq;
var interval=cpu1.idle-cpu0.idle;
return t0==t1?0:(1-interval/(t1-t0))*100;
while(1){
var cpu0=cpu_stat();
for(var i=0;i<5;i+=1){
unix.sleep(0.1);
coroutine.yield(nil);
}
var cpu1=cpu_stat();
var t0=cpu0.user+cpu0.nice+cpu0.system+cpu0.idle+cpu0.iowait+cpu0.irq+cpu0.softirq;
var t1=cpu1.user+cpu1.nice+cpu1.system+cpu1.idle+cpu1.iowait+cpu1.irq+cpu1.softirq;
var interval=cpu1.idle-cpu0.idle;
coroutine.yield(t0==t1?0:(1-interval/(t1-t0))*100);
}
}
var mem_occupation=func(){
@ -36,20 +42,24 @@ var mem_occupation=func(){
}
return mem_res;
}
func(){
if(os.platform()=="windows"){
println("haven't supported yet.");
return;
}
var co=coroutine.create(cpu_occupation);
var bar=process_bar.high_resolution_bar(30);
print("\ec");
while(1){
var mem=mem_occupation();
var mem_occ=(mem.MemTotal-mem.MemFree)/mem.MemTotal*100;
var cpu_occ=cpu_occupation();
var key=libkey.nonblock();
var bar=process_bar.high_resolution_bar(25);
if(key!=nil and chr(key)=="q")
break;
var cpu_occ=nil;
while((cpu_occ=coroutine.resume(co)[0])==nil){
var key=libkey.nonblock();
if(key!=nil and chr(key)=="q")
return;
}
println("\e[1;1H\e[1m Memory total(GB) : \e[0m\e[36m",mem.MemTotal/1024/1024,"\e[0m");
println("\e[2;1H\e[1m Memory free(GB) : \e[0m\e[36m",mem.MemFree/1024/1024,"\e[0m");
println("\e[3;1H\e[1m Memory occupation(%): \e[0m",mem_occ>60?"\e[91m":"\e[32m",bar.bar(mem_occ/100)~" ",mem_occ,"\e[0m ");