Call a foreign-language function: Difference between revisions
Content added Content deleted
m (→UASM 2.52) |
(updated ....) |
||
Line 2,783: | Line 2,783: | ||
<lang asm> |
<lang asm> |
||
option casemap:none |
option casemap:none |
||
option literals:on |
|||
windows64 equ 1 |
windows64 equ 1 |
||
Line 2,789: | Line 2,788: | ||
ifndef __LUA_CLASS__ |
ifndef __LUA_CLASS__ |
||
__LUA_CLASS__ equ 1 |
__LUA_CLASS__ equ 1 |
||
LUA_OK equ 0 |
|||
LUA_OK equ 0 |
|||
LUA_YEILD equ 1 |
|||
LUA_ERRRUN equ 2 |
|||
LUA_ERRSYNTAX equ 3 |
|||
LUA_ERRMEM equ 4 |
|||
;; Lua variable types - defined in lua.h |
|||
LUA_TNONE equ -1 |
|||
LUA_TNIL equ 0 |
|||
LUA_TBOOL equ 1 |
|||
LUA_TNUMB equ 3 |
|||
LUA_TSTRING equ 4 |
|||
LUA_TFUNC equ 6 |
|||
LUA_MULTRET equ -1 |
|||
;; to pop or not to pop, that is the question.. |
|||
DO_POP equ 1 |
|||
NO_POP equ 0 |
|||
if @Platform eq windows64 |
if @Platform eq windows64 |
||
Line 2,802: | Line 2,818: | ||
exit equ ExitProcess |
exit equ ExitProcess |
||
elseif @Platform eq linux64 |
elseif @Platform eq linux64 |
||
malloc proto SYSTEMV :qword |
malloc proto SYSTEMV :qword |
||
free proto SYSTEMV :qword |
free proto SYSTEMV :qword |
||
endif |
endif |
||
printf proto :qword, :vararg |
printf proto :qword, :vararg |
||
exit proto :dword |
exit proto :dword |
||
;; Lua.h funcs |
;; Lua.h funcs |
||
luaL_newstate proto ;; lua_State *luaL_newstate(); |
luaL_newstate proto ;; lua_State *luaL_newstate(); |
||
lua_gettop proto :qword ;; int lua_getopt(lua_State *L); |
lua_gettop proto :qword ;; int lua_getopt(lua_State *L); |
||
lua_close proto :qword ;; void lua_close(lua_State *L); |
lua_close proto :qword ;; void lua_close(lua_State *L); |
||
luaL_openlibs proto :qword ;; int luaL_openlibs(lua_State *L); |
luaL_openlibs proto :qword ;; int luaL_openlibs(lua_State *L); |
||
lua_pushnil proto :qword ;; void lua_pushnil(lua_State *L); |
|||
lua_pushinteger proto :qword, :qword ;; void lua_pushinteger(lua_State *L, lua_Integer arg); |
|||
lua_settop proto :qword, :dword ;; int lua_setopt(lua_State *L, int idx); |
|||
lua_setglobal proto :qword, :qword ;; void lua_setglobal(lua_State *L, const char *var); |
|||
lua_getglobal proto :qword, :qword ;; int lua_getglobal(lua_State *L, const char *gn); |
|||
luaL_loadstring proto :qword, :qword ;; int to_loadstring(lua_state *L, const char *string); |
|||
lua_pushstring proto :qword, :qword ;; const char *pushstring(lua_State *L, const char *var); |
|||
lua_pushboolean proto :qword, :dword ;; void lua_pushboolean(lua_State *L, int b) |
|||
lua_isinteger proto :qword, :dword ;; lua_Integer lua_isinteger(lua_State *L, int idx); |
|||
lua_tointegerx proto :qword, :dword,:dword ;; lua_Integer lua_tointeger(lua_State *L, int n); |
|||
luaL_loadfilex proto :qword, :qword,:dword ;; int luaL_loadfile(lua_State *L, const char *fn, const char *m) |
|||
;; void lua_pushcclosure(lua_State *L, lua_CFunction f, int n); |
|||
lua_pushccloure proto :qword, :qword, :dword |
|||
;; int lua_pcallk(lua_State *L, int argcnt, int results, int errfunc, int context, lua_CFunction k); |
|||
lua_pcallk proto :qword, :dword, :dword, :dword, :dword, :dword |
|||
CLASS lua_class |
CLASS lua_class |
||
CMETHOD |
CMETHOD run |
||
CMETHOD loadstring |
|||
CMETHOD loadfile |
|||
CMETHOD setglobal |
|||
CMETHOD getglobal |
|||
CMETHOD getstate |
|||
ENDMETHODS |
ENDMETHODS |
||
lua_state qword 0 |
lua_state qword 0 |
||
Line 2,831: | Line 2,864: | ||
.if rax != LUA_OK |
.if rax != LUA_OK |
||
invoke printf, CSTR("---> Lua failed to open libs",10) |
invoke printf, CSTR("---> Lua failed to open libs",10) |
||
jmp _ext |
|||
.endif |
.endif |
||
mov rax, rbx |
|||
_ext: |
|||
mov rax, rbx |
|||
assume rbx:nothing |
|||
ret |
|||
ENDMETHOD |
|||
;; dopop = pop off the virtual stack. |
|||
METHOD lua_class, run, <VOIDARG>, <>, narg:dword, nret:dword, dopop:word |
|||
mov rbx, thisPtr |
|||
assume rbx:ptr lua_class |
|||
invoke lua_pcallk, [rbx].lua_state, narg, nret, 0, 0, 0 |
|||
.if rax != LUA_OK |
|||
invoke printf, CSTR("--> lua_pcallk failed with %i",10), rax |
|||
.else |
|||
;; In some cases, we want to pop the top off the stack. But not always |
|||
;; so, DO_POP or NO_POP depending.. |
|||
.if dopop == DO_POP |
|||
invoke lua_gettop, [rbx].lua_state |
|||
not eax |
|||
invoke lua_settop, [rbx].lua_state, eax |
|||
.endif |
|||
.endif |
|||
assume rbx:nothing |
assume rbx:nothing |
||
ret |
ret |
||
ENDMETHOD |
ENDMETHOD |
||
METHOD lua_class, |
METHOD lua_class, loadstring, <VOIDARG>, <>, s:qword |
||
invoke luaL_loadstring, [thisPtr].lua_class.lua_state, s |
|||
local tmp:qword |
|||
ret |
|||
ENDMETHOD |
|||
METHOD lua_class, loadfile, <VOIDARG>, <>, fn:qword |
|||
mov rbx, thisPtr |
mov rbx, thisPtr |
||
assume rbx:ptr lua_class |
assume rbx:ptr lua_class |
||
invoke luaL_loadfilex, [rbx].lua_class.lua_state, fn, 0 |
|||
mov rax, s |
|||
invoke lua_pcallk, [rbx].lua_state, 0, LUA_MULTRET, 0, 0, 0 |
|||
mov tmp, rax |
|||
.if rax == LUA_OK |
|||
invoke luaL_loadstring, [rbx].lua_state, tmp |
|||
invoke lua_pcallk, [rbx].lua_state, 0, 0, 0, 0, 0 |
|||
.if rax != LUA_OK |
|||
invoke printf, CSTR("--> luaL_pcallk failed with %i",10), rax |
|||
.else |
|||
invoke lua_gettop, [rbx].lua_state |
invoke lua_gettop, [rbx].lua_state |
||
not eax |
not eax |
||
Line 2,855: | Line 2,910: | ||
mov rax, 0 |
mov rax, 0 |
||
assume rbx:nothing |
assume rbx:nothing |
||
ret |
|||
ENDMETHOD |
|||
;; lua_class.setglobals(qword ArumentVar, qword ArgumentReferenceName, dword LUA_TTYPE) |
|||
;; arg = String(char *) or boolean or integer. |
|||
;; an = argument reference name - The name used to reference arg1 from Lua code. |
|||
;; t = defined type of argument used. |
|||
METHOD lua_class, setglobal, <VOIDARG>, <>, arg:qword, an:qword, t:dword |
|||
local targ:qword |
|||
local ttype:dword |
|||
local tan:qword |
|||
mov rbx, thisPtr |
|||
assume rbx:ptr lua_class |
|||
mov targ, arg |
|||
mov ttype, t |
|||
mov tan, an |
|||
.if ttype == LUA_TNIL |
|||
invoke lua_pushnil, [rbx].lua_state |
|||
.elseif ttype == LUA_TBOOL |
|||
mov rax, targ |
|||
invoke lua_pushboolean, [rbx].lua_state, eax |
|||
.elseif ttype == LUA_TSTRING |
|||
invoke lua_pushstring, [rbx].lua_state, targ |
|||
.elseif ttype == LUA_TFUNC |
|||
;; Used for a lua function call.. But I'm lazy so, check the |
|||
;; Lua docs for info about that... |
|||
.else |
|||
;; Assumes it's an Integer type. Lua's integers are int or long sized(set in luaconfig.h). |
|||
;; so qword sized variable to be safe. |
|||
invoke lua_pushinteger, [rbx].lua_state, targ |
|||
.endif |
|||
invoke lua_setglobal, [rbx].lua_state, tan |
|||
assume rbx:nothing |
|||
ret |
|||
ENDMETHOD |
|||
METHOD lua_class, getglobal, <VOIDARG>, <>, gn:qword |
|||
invoke lua_getglobal, [thisPtr].lua_class.lua_state, gn |
|||
ret |
|||
ENDMETHOD |
|||
METHOD lua_class, getstate, <VOIDARG>, <> |
|||
mov rax, [thisPtr].lua_class.lua_state |
|||
ret |
ret |
||
ENDMETHOD |
ENDMETHOD |
||
Line 2,868: | Line 2,967: | ||
ENDMETHOD |
ENDMETHOD |
||
endif ;__LUA_CLASS__ |
endif ;; __LUA_CLASS__ |
||
.data |
|||
d1 dq 1342 |
|||
d2 dq 1551 |
|||
pFile db "addition.lua",0 |
|||
.code |
.code |
||
main proc |
main proc |
||
local lvm:ptr lua_class |
local lvm:ptr lua_class |
||
local state:qword |
|||
invoke printf, CSTR("-> Attempting to init Lua...",10) |
invoke printf, CSTR("-> Attempting to init Lua...",10) |
||
mov lvm, _NEW(lua_class) |
mov lvm, _NEW(lua_class) |
||
lvm->getstate() |
|||
invoke printf, CSTR("-> Lua started, Running first test..",10) |
|||
mov state, rax |
|||
lvm->runstr(CSTR("print('Goodbye, world from Lua..')")) |
|||
invoke printf, CSTR("-> LVM started, Using loadstring..",10) |
|||
lvm->loadstring(CSTR("print('---> Goodbye, world from Lua..')")) |
|||
lvm->run(0,0, DO_POP) |
|||
lvm->setglobal(CSTR("A string that's global"), CSTR("teststr"), LUA_TSTRING) |
|||
lvm->setglobal(12, CSTR("numb"), LUA_TNONE) |
|||
lvm->loadstring(CSTR("print('---> Global str: ' .. teststr .. '\n---> Global int: ' .. numb)")) |
|||
lvm->run(0, 0, DO_POP) |
|||
invoke printf, CSTR("-> Loading lua file...",10) |
|||
lea rax, pFile |
|||
lvm->loadfile(rax) |
|||
.if rax != LUA_OK |
.if rax != LUA_OK |
||
invoke printf, CSTR("-> |
invoke printf, CSTR("-> Failed loadfile, returned with: %i",10), rax |
||
jmp _ext |
jmp _ext |
||
.endif |
.endif |
||
lvm->getglobal(CSTR("addition")) |
|||
.if rax != LUA_TFUNC |
|||
invoke printf, CSTR("-> Global wasn't a function",10,"-> Type retruned is: %d",10), rax |
|||
jmp _ext |
|||
.endif |
|||
;; We're just pushing the ints onto the Virtual stack for arguments |
|||
invoke lua_pushinteger, state, d1 |
|||
invoke lua_pushinteger, state, d2 |
|||
lvm->run(2,1,NO_POP) |
|||
.if rax == LUA_OK |
|||
invoke lua_isinteger, state, -1 |
|||
.if rax != 1 |
|||
invoke printf, CSTR("-> Value is NOT an integer..",10) |
|||
jmp _ext |
|||
.endif |
|||
invoke lua_tointegerx, state, -1, 0 |
|||
push rax |
|||
;; Set the top of the virtual stack to our return value.. |
|||
invoke lua_settop, state, 1 |
|||
pop rax |
|||
invoke printf, CSTR("-> Return from lua func: %i",10), eax |
|||
.else |
|||
invoke printf, CSTR("-> lvm->run() failed to call func returned: %i",10), rax |
|||
.endif |
|||
_ext: |
_ext: |
||
_DELETE(lvm) |
_DELETE(lvm) |
||
Line 2,888: | Line 3,027: | ||
main endp |
main endp |
||
end |
|||
</lang> |
|||
Addition.lua |
|||
<lang lua> |
|||
function addition(a, b) |
|||
print('---> Lua calc: ' .. a .. ' + ' .. b .. ' = ' .. a+b) |
|||
return a + b |
|||
end |
end |
||
</lang> |
</lang> |
||
Line 2,893: | Line 3,039: | ||
<pre> |
<pre> |
||
-> Attempting to init Lua... |
-> Attempting to init Lua... |
||
-> |
-> LVM started, Using loadstring.. |
||
Goodbye, world from Lua.. |
---> Goodbye, world from Lua.. |
||
---> Global str: A string that's global |
|||
---> Global int: 12 |
|||
-> Loading lua file... |
|||
---> Lua calc: 1342 + 1551 = 2893 |
|||
-> Return from lua func: 2893 |
|||
</pre> |
</pre> |
||
When I stop being lazy and/or drunk, I'll update the class to run a lua script file... |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |