I'm trying to do this using nimLua and running it in Love2D.
I'm not sure how to do this though. I watched a tutorial on how to do this in C, and I tried something similar, but ofc it doesn't work:
# sllib.nim
import nimlua
proc foo*(L:PState):cint {.stdcall, exportc, dynlib.} =
echo "I AM THE FOO!!!"
L.pushnumber(10)
return 1
proc luaopen_test*(L:PState):cint {.stdcall, exportc, dynlib.} =
L.bindFunction("foo", foo)
return 0
I presume I need those pragmas. I read somewhere about them.
So I compiled to a dll, but then when I do require "sllib" in lua, it crashes my app.
I don't know what to do...
I presume I need those pragmas. I read somewhere about them. I've no idea if I should export the procs, I've no idea if they should return cint, and I've no idea if any of that makes any sense.
I can't answer your question, but I love your honesty. :-)
At first sight, i thought « oh, must be a ref missing for function in the bind ».
It seems more difficult, look at this project: https://github.com/jangko/nimLUA
it's not exactly what you want to do, but a lot of pitfalls are already covered.
import nimLUA
proc foo*(L:PState): int =
echo "I AM THE FOO!!!"
return 1
proc luaopen_test*(L:PState) =
L.bindFunction("foo", foo)
proc main() =
var L = newNimLua()
L.luaopen_test
L.doFile("test.lua") # This is the Lua code we want to embed
L.close()
main()
With a companion Lua script, called test.lua that includes only the following line:
print(foo:foo())
When the Nim code is compiled and executed, without special flags, just nim c -r yourcode.nim:
I AM THE FOO!!! 1
So, in summary, you are more embeding "test.lua" script in your Nim program than calling Nim code from the Lua script. But it is true that the Lua script can call the Nim procedures.
If you want to compile the above Nim code as a DLL and then call it from a Lua script, rewrite the Nim file as:
proc foo*(): cint {.cdecl,exportc,dynlib.} =
echo "I AM THE FOO!!!"
return 1
Yes, now we have to use the three pragmas that indicates the compiler that we are compiling a procedure that must be called with C conventions, is going to be exported and compiled as a dynamic library , with the following command:
nim c --app:lib mylib.nim
A new file called libmylib.dll should be created. Now your Lua script can call this DLL using the following code:
local ffi = require("ffi") local mylib = ffi.load("libmylib") ffi.cdef[[ int foo(); ]] print(mylib.foo())
With the following results:
$ luajit test.lua I AM THE FOO!!! 1
Hope this helps!
Definitely helping. :D
In my case it doesn't print the string though, only the int that is returned. Probably something to do with running it in Love2d.
Still need to transfer data to and from nim <-> lua though, or else I'll have no use for it. The return value doesn't seem to be good. I could do this with nimLua, using lua's stacks (L.pushnumber, etc), but I'm not getting it to work...
Problem is, Nim procs need a PState to work with, and I can't get the lua_State from lua. I'm don't suppose Love2D exposes it either.
Here's what I tried:
#sllib.nim
import nimlua
proc foo(L:PState): cint {.cdecl, exportc, dynlib.} =
echo "I AM THE FOO!!!"
L.pushnumber(10)
# in C, the return value is the stack slot, which lua can access
# (-1 is the top of the stack, iirc)
return -1
local ffi = require("ffi")
local sllib = ffi.load("sllib")
ffi.cdef [[
typedef struct lua_State lua_State;
int foo(lua_State *L);
]]
print(sllib.foo()) -- Error: wrong number of arguments for function call
I just did it!! :D
I managed to make it work using the official lua bindings.
import lua
proc nimfoo(L:PState): cint {.cdecl.} =
pushnumber(L, 10)
pushstring(L, "bla bla bla")
result = 2 -- two values in the lua stack
# this gets called automatically during 'require', so maybe here we can set
# a namespace, but I don't know how, yet
# luaopen_ + libname (or else: ERROR)
proc luaopen_sllib(L:PState):cint {.cdecl, exportc, dynlib.} =
register(L, "foo", nimfoo)
result = 0
local sllib = require("sllib")
local n, s = foo()
print(n, s) -- 10 bla bla bla
Thanks @xbello. I was really totally in the dark before your post. You helped a whole bunch. :)