Hey Skaruts, I'm not sure what you are trying to do with Love2D, but I thought 
this might interest you so I'll paste it here.

It's a demo using the Love API via the Lua VM:
    
    
    # main.nim
    
    # -- a bunch of glue code to get lua working --
    
    type
      luacfunc = proc(luaState: pointer): cint
      luaL_reg = object
        name: cstring
        function: luacfunc
      
      luaL_reg_ref = ref luaL_reg
      luaL_reg_list = array[3, luaL_reg]
    
    proc reg(name: cstring, function: luacfunc): luaL_reg_ref =
      new result
      result.name = name
      result.function = function
    
    const luaGlobalsIndex = -10002
    const luaRegistryIndex = -10000
    var luaState: pointer
    
    proc luaL_ref(lua_State: pointer, t: cint): cint {.importc: "luaL_ref".}
    proc luaL_openlib(luaState: pointer, name: cstring, lib: luaL_reg_list, 
someval: cint) {.importc: "luaL_openlib".}
    proc lua_settop(luaState: pointer, index: cint) {.importc: "lua_settop".}
    proc rawgeti(luaState: pointer, index1, index2: cint) {.importc: 
"lua_rawgeti".}
    proc pop(luaState: pointer, index: cint) = lua_settop(luaState,-(index)-1)
    proc getfield(luaState: pointer, a: cint, name: cstring) {.importc: 
"lua_getfield".}
    proc setfield(luaState: pointer, a: cint, name: cstring) {.importc: 
"lua_setfield".}
    proc luaPcall(luaState: pointer, a, b, c: cint): cint {.importc: 
"lua_pcall".}
    
    proc luaToString(luaState: pointer, index: cint, size: cint): cstring 
{.importc: "lua_tolstring".}
    proc luaToNumber(luaState: pointer, index: cint): cdouble {.importc: 
"lua_tonumber".}
    proc luaToBool(luaState: pointer, index: cint): cint {.importc: 
"lua_toboolean".}
    
    proc pushNumber(luaState: pointer, number: cdouble) {.importc: 
"lua_pushnumber".}
    proc pushString(luaState: pointer, s: cstring) {.importc: "lua_pushstring".}
    proc pushCClosure(luaState: pointer, function: pointer, a: cint) {.importc: 
"lua_pushcclosure".}
    proc pushFunction(luaState: pointer, function: pointer) = 
luaState.pushCClosure(function, 0)
    
    proc pullString(luaState: pointer, index: cint): string = 
$luaToString(luaState, index, 0)
    proc pullNumber(luaState: pointer, index: cint): float = 
luaToNumber(luaState, index)
    proc pullBool(luaState: pointer, index: cint): bool = return 
luaToBool(luaState, index) == 1
    
    proc loveFunc(moduleName, funcName: string) =
      getfield(luaState, luaGlobalsIndex, "love")
      getfield(luaState, -1, moduleName)
      getfield(luaState, -1, funcName)
    
    # -- api wrapper --
    
    type Image = distinct cint
    
    proc newImage(filename: string): Image =
      loveFunc("graphics", "newImage")
      luaState.pushString(filename)
      if luaPcall(luaState, 1, 1, 0) != 0:
        echo "proc newImage failed on the lua side ->", luaState.pullString(-1)
        quit 1
      let res = luaState.luaL_ref(luaRegistryIndex).Image
      luaState.pop(1)
      return res
    
    proc getWidth(self: Image): float =
      luaState.rawgeti(luaRegistryIndex, self.cint)
      getfield(luaState, -1, "getWidth")
      luaState.rawgeti(luaRegistryIndex, self.cint)
      if luaPcall(luaState, 1, 1, 0) != 0:
        echo "proc getWidth failed on the lua side ->", luaState.pullString(-1)
        quit 1
      let res = luaState.pullNumber(-1)
      luaState.pop(1)
      return res
    
    proc getHeight(self: Image): float =
      luaState.rawgeti(luaRegistryIndex, self.cint)
      getfield(luaState, -1, "getHeight")
      luaState.rawgeti(luaRegistryIndex, self.cint)
      if luaPcall(luaState, 1, 1, 0) != 0:
        echo "proc getHeight failed on the lua side ->", luaState.pullString(-1)
        quit 1
      let res = luaState.pullNumber(-1)
      luaState.pop(1)
      return res
    
    proc draw(
      image: Image,
      x: float,  # The position to draw the object (x-axis).
      y: float,  # The position to draw the object (y-axis).
      r: float,  # Orientation (radians).
      sx: float,  # Scale factor (x-axis). Can be negative.
      sy: float,  # Scale factor (y-axis). Can be negative.
      ox: float,  # Origin offset (x-axis). (A value of 20 would effectively 
move your drawable object 20 pixels to the left.)
      oy: float,  # Origin offset (y-axis). (A value of 20 would effectively 
move your drawable object 20 pixels up.)
      kx: float,  # Shearing factor (x-axis).
      ky: float  # Shearing factor (y-axis).
    ) =
      loveFunc("graphics", "draw")
      luaState.rawgeti(luaRegistryIndex, image.cint)
      luaState.pushNumber(x)
      luaState.pushNumber(y)
      luaState.pushNumber(r)
      luaState.pushNumber(sx)
      luaState.pushNumber(sy)
      luaState.pushNumber(ox)
      luaState.pushNumber(oy)
      luaState.pushNumber(kx)
      luaState.pushNumber(ky)
      if luaPcall(luaState, 10, 0, 0) != 0:
        echo "proc draw failed on the lua side ->", luaState.pullString(-1)
        quit 1
    
    proc quitLove =
      loveFunc("event", "quit")
      if luaPcall(luaState, 0, 0, 0) != 0:
        echo "proc quit failed on the lua side ->", luaState.pullString(-1)
        quit 1
    
    # -- app code below --
    
    var image: Image
    
    proc loadCallback =
      image = newImage("sprite.png")
      echo "Image width  (should be 300): ", image.getWidth()
      echo "Image height (should be 205): ", image.getHeight()
    
    proc drawCallback =
      draw(image, 10, 10, 0, 1, 1, 0, 0, 0, 0)
    
    proc keypressedCallback(key, scancode: string, isrepeat: bool) =
      if key == "escape":
        quitLove()
    
    # -- init --
    
    proc drawWrapper(state: pointer): cint =
      luaState = state
      drawCallback()
    
    proc loadWrapper(state: pointer): cint =
      luaState = state
      loadCallback()
    
    proc keypressedWrapper(state: pointer): cint =
      luaState = state
      let key = state.pullString(1)
      let scancode = state.pullString(2)
      let isrepeat = state.pullBool(3)
      keypressedCallback(key, scancode, isrepeat)
    
    proc load(L: pointer): cint {.dynlib, exportc: "luaopen_libmain".} =
      {.emit: """NimMain();""".}
      luaState = L
      echo "lua opened nim lib"
      var mylib: luaL_reg_list = [
        reg(nil, nil)[],
        reg(nil, nil)[],
        reg(nil, nil)[]
      ]
      luaL_openlib(L, "libmain", mylib, 0)
      
      pushFunction(L, drawWrapper)
      setfield(L, luaGlobalsIndex, "draw")
      
      pushFunction(L, keypressedWrapper)
      setfield(L, luaGlobalsIndex, "keypressed")
      
      pushFunction(L, loadWrapper)
      setfield(L, luaGlobalsIndex, "load")
      
      return 1
    
    
    Run
    
    
    -- main.lua
    
    
    require "libmain"
    
    function love.load ()
      load()
    end
    
    function love.draw ()
      draw()
    end
    
    function love.keypressed (key, scanCode, isRepeat)
      keypressed(key, scanCode, isRepeat)
    end
    
    
    Run

Compile and run:
    
    
    nim c --app:lib main.nim && love .
    
    
    Run

Result:

You would think that interacting with the engine by going [Nim]-->[Lua]-->[C++] 
would be slow but it actually doesn't seem to incur much overhead compared to 
just [Lua]-->[C++]

Reply via email to