LUA module coded in PB

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

LUA module coded in PB

Post by eddy »

PB code of MyModule.dll:

Code: Select all

; ********************
; LUA API (Tested with Lua5.1 x64)
; Remark: it's an incomplete list, feel free to add missing API and examples
; ********************
CompilerIf #PB_Compiler_ExecutableFormat=#PB_Compiler_DLL
   DeclareModule LuaModule
      Enumeration LUA_TYPE         
         #LUA_TNONE=-1         
         #LUA_TNIL=0
         #LUA_TBOOLEAN 
         #LUA_TLIGHTUSERDATA 
         #LUA_TNUMBER 
         #LUA_TSTRING 
         #LUA_TTABLE 
         #LUA_TFUNCTION 
         #LUA_TUSERDATA 
         #LUA_TTHREAD 
      EndEnumeration
      
      PrototypeC lua_error(*L)
      PrototypeC lua_gettop(*L)
      PrototypeC lua_setfield(*L, field.i, stringField.p-ascii)      
      PrototypeC.i lua_toboolean(*L, idx)
      PrototypeC.i lua_tointeger(*L, idx)
      PrototypeC lua_pushstring(*L, stringMessage.p-utf8)
      PrototypeC lua_pushnumber(*L, number.d)
      PrototypeC lua_createtable(*L, narr.i, nrec.i)
      PrototypeC lua_pushcclosure(*L, *functionName, n.i)
      PrototypeC luaL_error(*L, stringError.p-ascii)
      PrototypeC luaL_checktype(*L, idx, LUA_TYPE)
      PrototypeC.d luaL_checknumber(*L, arg.i)
      PrototypeC.i luaL_checkinteger(*L, arg.i)
      PrototypeC.i luaL_checkboolean(*L, arg.i)
      PrototypeC.s luaL_checkstring(*L, arg.i)
      PrototypeC.i luaL_checklstring(*L, arg.i, *argStringLength.Integer)
      Global lua_error.lua_error
      Global lua_gettop.lua_gettop
      Global lua_setfield.lua_setfield
      Global lua_toboolean.lua_toboolean
      Global lua_tointeger.lua_tointeger
      Global lua_pushstring.lua_pushstring
      Global lua_pushnumber.lua_pushnumber
      Global lua_createtable.lua_createtable
      Global lua_pushcclosure.lua_pushcclosure      
      Global luaL_error.luaL_error
      Global luaL_checktype.luaL_checktype
      Global luaL_checknumber.luaL_checknumber
      Global luaL_checkinteger.luaL_checkinteger
      Global luaL_checklstring.luaL_checklstring
      Global luaL_checkstring.luaL_checkstring
      Global luaL_checkboolean.luaL_checkboolean
      
      Declare.i LoadLuaAPI()
   EndDeclareModule   
   
   Module LuaModule
      Procedure luaL_checktype_toboolean(*L, arg.i)
         ProcedureReturn Bool(luaL_checktype(*L, arg, #LUA_TBOOLEAN))*lua_toboolean(*L, arg)
      EndProcedure
      
      Procedure.s luaL_checklstring_tostring(*L, arg.i)
         Protected argLen.Integer
         ProcedureReturn PeekS(luaL_checklstring(*L, 2, @argLen), argLen\i, #PB_UTF8)
      EndProcedure
      
      Procedure LoadLuaAPI()
         If OpenLibrary(1, "lua51.dll")
               ;load LUA API
               lua_error=GetFunction(1, "lua_error")
               lua_gettop=GetFunction(1, "lua_gettop")
               lua_setfield=GetFunction(1, "lua_setfield")
               lua_toboolean=GetFunction(1, "lua_toboolean")
               lua_tointeger=GetFunction(1, "lua_tointeger")
               lua_pushstring=GetFunction(1, "lua_pushstring")
               lua_pushnumber=GetFunction(1, "lua_pushnumber")
               lua_createtable=GetFunction(1, "lua_createtable")
               lua_pushcclosure=GetFunction(1, "lua_pushcclosure")
               luaL_error=GetFunction(1, "luaL_error")
               luaL_checktype=GetFunction(1, "luaL_checktype")
               luaL_checknumber=GetFunction(1, "luaL_checknumber")
               luaL_checkinteger=GetFunction(1, "luaL_checkinteger")
               luaL_checklstring=GetFunction(1, "luaL_checklstring")
               ;load LUA shorthand
               luaL_checkstring=@luaL_checklstring_tostring()
               luaL_checkboolean=@luaL_checktype_toboolean()
               CloseLibrary(1)
               ProcedureReturn #True
         EndIf
      EndProcedure
   EndModule
CompilerEndIf

CompilerIf #PB_Compiler_IsMainFile
   UseModule LuaModule
   
   ; ********************
   ; Custom LUA methods
   ; ********************
   ProcedureCDLL getMessage(*L)
      If(lua_gettop(*L)<>4)
         luaL_error(*L, "4 mandatory arguments are expected.")   ; 1st result (ERROR)
         ProcedureReturn 1                                       ; ** number of results **
      Else
         ; Get 1st argument as Integer
         Protected arg1=luaL_checkinteger(*L, 1)
         ; Get 2nd argument as String
         Protected arg2$=luaL_checkstring(*L, 2)
         ; Get 3rd argument as Double
         Protected arg3.d=luaL_checknumber(*L, 3)
         ; Get 4th argument as Boolean
         Protected arg4.b=luaL_checkboolean(*L, 4)
      EndIf
      
      If arg4
         Protected result$=arg2$ + " " + "ǽ" + " " + arg1 + " " + arg3
         lua_pushstring(*L, result$)   ; 1st result
         ProcedureReturn 1             ; ** number of results **
      EndIf
   EndProcedure
   
   ProcedureCDLL getDimensions(*L)
      lua_pushnumber(*L, 10)     ; 1st result
      lua_pushnumber(*L, 20)     ; 2nd result
      ProcedureReturn 2          ; ** number of results **
   EndProcedure
   
   ; ********************
   ; Custom LUA module
   ; ********************
   ProcedureCDLL luaopen_MyModule(*L)
      If *L And LoadLuaAPI()
         ;declare LUA module
         lua_createtable(*L, 0, 0)                                                           ; 1st result (table of methods)
         lua_pushcclosure(*L, @getMessage(), 0) : lua_setfield(*L, -2, "getMessage")         ;    => Declare 1st method
         lua_pushcclosure(*L, @getDimensions(), 0) : lua_setfield(*L, -2, "getDimensions")   ;    => Declare 2nd method
         ProcedureReturn 1                                                                   ; ** number of results **
      EndIf
   EndProcedure
CompilerEndIf
LUA code of Test.lua:

Code: Select all

  local MyModule = require("MyModule") -- => loading MyModule.dll => executing luaopen_MyModule()
  
  local w, h = MyModule.getDimensions()    
  print("getDimensions: " .. w .. " " .. h)
  
  local result = MyModule.getMessage(1,"Holé!", 3.5, true)
  print(result) 
Last edited by eddy on Sun Apr 02, 2017 10:21 am, edited 9 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Fred
Administrator
Administrator
Posts: 16686
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: LUA module coded in PB

Post by Fred »

Nice ! Also, don't forget, Ascii() result needs to be freed.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: LUA module coded in PB

Post by ts-soft »

UTF8() also :wink:
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: LUA module coded in PB

Post by eddy »

Fred wrote:Nice ! Also, don't forget, Ascii() result needs to be freed.
ts-soft wrote:UTF8() also :wink:
Damn, in my mind, there were some kind of macro for string conversion.
I didn't read the doc for these two commands :mrgreen:
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: LUA module coded in PB

Post by eddy »

updated 2
- luaL_checkboolean : shorthand to get boolean argument
- luaL_checkstring : shorthand to get string argument
- luaL_checktype : API to check LUA supported types
- LUA supported types enumeration

updated 1
- pointer string arguments have been replaced by pseudo-type string arguments (p-utf8 and p-ascii)
- Ascii() and UTF8() have been removed in the example.

It's easier to code.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Post Reply