在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):jangko/nimLUA开源软件地址(OpenSource Url):https://github.com/jangko/nimLUA开源编程语言(OpenSource Language):Nim 94.1%开源软件介绍(OpenSource Introduction):nimLuaglue code generator to bind Nim and Lua together using Nim's powerful macro Features:
planned features:
Current version API: no need to remember complicated API, the API is simple but powerful
DATA TYPE CONVERSION
HOW TO USE1. bindEnumimport nimLUA, os
type
FRUIT = enum
APPLE, BANANA, PEACH, PLUM
SUBATOM = enum
ELECTRON, PROTON, NEUTRON
GENE = enum
ADENINE, CYTOSINE, GUANINE, THYMINE
proc test(L: PState, fileName: string) =
if L.doFile("test" & DirSep & fileName) != 0.cint:
echo L.toString(-1)
L.pop(1)
else:
echo fileName & " .. OK"
proc main() =
var L = newNimLua()
L.bindEnum(FRUIT, SUBATOM, GENE)
L.test("test.lua")
L.close()
main() and you can access them at Lua side like this: assert(FRUIT.APPLE == 0)
assert(FRUIT.BANANA == 1)
assert(FRUIT.PEACH == 2)
assert(FRUIT.PLUM == 3)
assert(GENE.ADENINE == 0)
assert(GENE.CYTOSINE == 1)
assert(GENE.GUANINE == 2)
assert(GENE.THYMINE == 3)
assert(SUBATOM.ELECTRON == 0)
assert(SUBATOM.PROTON == 1)
assert(SUBATOM.NEUTRON == 2) another style: L.bindEnum:
FRUIT
SUBATOM
GENE if you want to rename the namespace, you can do this: L.bindEnum:
GENE -> "DNA"
SUBATOM -> GLOBAL or L.bindEnum(GENE -> "DNA", SUBATOM -> GLOBAL) a note on GLOBAL and "GLOBAL":
now Lua side will become: assert(DNA.ADENINE == 0)
assert(DNA.CYTOSINE == 1)
assert(DNA.GUANINE == 2)
assert(DNA.THYMINE == 3)
assert(ELECTRON == 0)
assert(PROTON == 1)
assert(NEUTRON == 2) 2. bindConstimport nimLUA
const
MANGOES = 10.0
PAPAYA = 11.0'f64
LEMON = 12.0'f32
GREET = "hello world"
connected = true
proc main() =
var L = newNimLua()
L.bindConst(MANGOES, PAPAYA, LEMON)
L.bindConst:
GREET
connected
L.close()
main() by default, bindConst will not generate namespace, so how do you create namespace for const? easy: L.bindConst("fruites", MANGOES, PAPAYA, LEMON)
L.bindConst("status"):
GREET
connected first argument(actually second) to bindConst will become the namespace. Without namespace, symbol will be put into global namespace if you use GLOBAL without quote as namespace, it will have no effect operator 3. bindFunction/bindProcbindFunction is an alias to bindProc, they behave identically import nimLUA
proc abc(a, b: int): int =
result = a + b
var L = newNimLua()
L.bindFunction(abc)
L.bindFunction:
abc -> "cba"
L.bindFunction("alphabet", abc) bindFunction more or less behave like bindConst, without namespace, it will bind symbol to global namespace. overloaded procs will be automatically resolved by their params count and types operator 4. bindObjectimport nimLUA
type
Foo = ref object
name: string
proc newFoo(name: string): Foo =
new(result)
result.name = name
proc addv(f: Foo, a, b: int): int =
result = 2 * (a + b)
proc addv(f: Foo, a, b: string): string =
result = "hello: my name is $1, here is my message: $2, $3" % [f.name, a, b]
proc addk(f: Foo, a, b: int): string =
result = f.name & ": " & $a & " + " & $b & " = " & $(a+b)
proc main() =
var L = newNimLua()
L.bindObject(Foo):
newFoo -> constructor
addv
addk -> "add"
L.close()
main() this time, Foo will become object name and also namespace name in Lua "newFoo L.bindObject(Foo):
newFoo #constructor #1 'newFoo'
newFoo -> constructor #constructor #2 'new'
newFoo -> "whatever" #constructor #3 'whatever'
makeFoo -> "constructor" #constructor #4 'constructor' operator overloaded proc will be automatically resolved by their params count and types, including overloaded constructor destructor will be generated automatically for ref object, none for regular object. GC safety works as usual on both side of Nim and Lua, no need to worry, except when you manually allocated memory local foo = Foo.new("fred")
local m = foo:add(3, 4)
-- "fred: 3 + 4 = 7"
print(m)
assert(foo:addv(4,5) == 2 * (4+5))
-- "hello: my name is fred, here is my message: abc, nop"
print(foo:addv("abc", "nop")) operator L.bindObject(Foo -> "cat"):
newFoo -> constructor on Lua side: local c = cat.new("fred") --not 'Foo' anymore both bindObject and bindFunction and bindConst can add member to existing namespace if you want to turn off this functionality, call nimLuaOptions(nloAddMember, false) L.bindObject(Foo): #namespace creation
newFoo -> constructor
L.bindObject(Foo): #add new member
addv
addk -> "add"
L.bindFunction("gem"): #namespace "gem" creation
mining
L.bindFunction("gem"): #add 'polish' member
polish 4.1. bindObject without memberIt's ok to call bindObject without any additional member/method if you want to register object type and use it later. For example if you want to create your own object constructor 4.2. bindObject for opaque C pointerUsually a C library have constructor(s) and destructor function. The constructor will return an opaque pointer. On Nim side, we usually use something like: type
CContext* = distinct pointer
proc createCContext*(): CContext {.cdecl, importc.}
proc deleteCContext*(ctx: CContext) {.cdecl, importc.} Of course this is not an object or ref object, but we treat it as an object in this case.
Therefore bindObject will work like usual.
Only this time, we also need to specify the destructor function using L.bindObject(CContext):
createCContext -> "create"
~deleteCContext PASSING BY REFERENCELua basic data types cannot be passed by reference, but Nim does if you have something like this in Nim: proc abc(a, b: var int) =
a = a + 1
b = b + 5 then on Lua side: a = 10
b = 20
a, b = abc(a, b)
assert(a == 11)
assert(b == 25) basically, outval will become retval, FIFO ordered GENERIC PROC BINDINGproc mew[T, K](a: T, b: K): T =
discard
L.bindFunction:
mew[int, string]
mew[int, string] -> "mewt" CLOSURE BINDINGproc main() =
...
var test = 1237
proc cl() =
echo test
L.bindFunction:
[cl]
[cl] -> "clever" GETTER/SETTERtype
Ship = object
speed*: int
power: int
L.bindObject(Ship):
speed(set)
speed(get) -> "currentSpeed"
speed(get, set) -> "velocity" then you can access the object's properties on lua side using '.' (dot) and not ':' (colon) local b = Ship.newShip()
b.speed = 19
assert(b.speed == nil) -- setter only
assert(b.currentSpeed == 19) -- getter only
b.velocity = 20
assert(b.velocity == 20) -- getter & setter HOW TO DEBUGyou can call nimLuaOptions(nloDebug, true/false) nimLuaOptions(nloDebug, true) #turn on debug
L.bindEnum:
GENE
SUBATOM
nimLuaOptions(nloDebug, false) #turn off debug mode
L.bindFunction:
machine
engine DANGEROUS ZONElua_error, lua_checkstring, lua_checkint, lua_checkudata and other lua C API that can throw error
are dangerous functions when called from Nim context. lua_error use Although Nim compiled to C, Nim have it's own stack frame. Calling lua_error and other functions that can throw error will disrupt Nim stack frame, and application will crash. nimLUA avoid using those dangerous functions and and use it's own set of functions that is considerably safe. those functions are:
Error Handling NLError* = object
source: string
currentLine: int
msg: string
NLErrorFunc* = proc(ctx: pointer, err: NLError) {.nimcall.}
proc NLSetErrorHandler*(L: PState, errFunc: NLErrorFunc)
proc NLSetErrorContext*(L: PState, errCtx: pointer) This is actually not a real error handler, because you cannot use raise exception. The purpose of this function is to provide information to user about wrong argument type passed from Lua to Nim. nimLUA already provide a default error handler in case you forget to provide one. HOW TO ACCESS LUA CODE FROM NIM?still under development, contributions are welcome Installation via nimble
Override shared library nameYou can use compiler switch $> nim c -r -d:SHARED_LIB_NAME="lua534.dll" test/test |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论