gengyong / luaaa Goto Github PK
View Code? Open in Web Editor NEWC++ to LUA binding tool in a single header file.
License: MIT License
C++ to LUA binding tool in a single header file.
License: MIT License
no action really required but FYI-ish, we had to implement the following change for luaaa to compile in our environment
how can i call a lua method from c++?
like emit events, for example:
C++:
void Update(){
luaIdkBlaBla.emit("onUpdate");
}
Lua:
func onUpdate():
print("updated")
end
and so the lua function is called from the c++ code
using example.lua
and LUA tutorial I tried to subclass AwesomeCat like so
SpecialCat = AwesomeCat:new("special")
function SpecialCat:onlyInSpecial()
print(self.getName() .. " has a special cat function")
end
function SpecialCat:speak(text)
print("Special cat says: " .. text)
end
This should add a new function onlyInSpecial
to SpecialCat and overwrite speak
but that does not seem to work. LUA refuses AwesomeCat:new
with
lua err: [string "console"]:60: calling 'new' on bad self (string expected, got table)
using AwesomeCat.new
works, but then I am not allowed to add new functions to SpecialCat
lua err: [string "console"]:61: attempt to index a AwesomeCat value (global 'SpecialCat')
Is this possible at all and if so how to do this?
support multiple return values from C++ functions
Hey,
thanks for this great work.
I am trying to require a lua module into the example.lua file and getting lua error.
Two questions:
Thanks.
Is inheritance supported? E.g. binding something like.
class Animal { ... };
class Cat: public Animal { ... };
class Tiger: public Cat { ... };
void AddToZoo(Animal& animal); // Should be callable with a Cat or a Tiger
I take a static global variable and make it static class variable - things stop linking.
Code links just fine:
struct LuaCanReciever;
// linked list of all CAN receivers
static LuaCanReciever *list;
struct LuaCanReciever {
LuaCanReciever *next;
~LuaCanReciever() {
LuaCanReciever *current, *tmp;
// find self in list and remove self
LL_FOREACH_SAFE(list, current, tmp)
{
if (current == this) {
LL_DELETE(list, current);
}
}
}
LuaCanReciever() {
LL_PREPEND(list, this);
}
};
LuaClass<LuaCanReciever> luaCanReciever(l, "CanReciever");
luaCanReciever
.ctor()
;
Code does not link
struct LuaCanReciever;
struct LuaCanReciever {
// linked list of all CAN receivers
static LuaCanReciever *list;
LuaCanReciever *next;
~LuaCanReciever() {
LuaCanReciever *current, *tmp;
// find self in list and remove self
LL_FOREACH_SAFE(list, current, tmp)
{
if (current == this) {
LL_DELETE(list, current);
}
}
}
LuaCanReciever() {
LL_PREPEND(list, this);
}
};
LuaClass<LuaCanReciever> luaCanReciever(l, "CanReciever");
luaCanReciever
.ctor()
;
with the following error:
Compiling lua_hooks.cpp
Linking build/rusefi.elf
c:/program files (x86)/gnu arm embedded toolchain/9 2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld.exe: C:\Users\Dell2019\AppData\Local\Temp\rusefi.elf.FKMdel.ltrans5.ltrans.o: in function `luaaa::LuaClass<LuaCanReciever>::LuaClass(lua_State*, char const*, luaL_Reg const*)::HelperClass::f__gc(lua_State*)':
C:\stuff\rusefi\firmware/./controllers/lua/lua_hooks.cpp:355: undefined reference to `LuaCanReciever::list'
c:/program files (x86)/gnu arm embedded toolchain/9 2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld.exe: C:\Users\Dell2019\AppData\Local\Temp\rusefi.elf.FKMdel.ltrans5.ltrans.o: in function `luaaa::LuaClass<LuaCanReciever>::ctor<>(char const*)::HelperClass::f_new(lua_State*)':
C:\stuff\rusefi\firmware/./controllers/lua/lua_hooks.cpp:355: undefined reference to `LuaCanReciever::list'
collect2.exe: error: ld returned 1 exit status
make: *** [ChibiOS/os/common/startup/ARMCMx/compilers/GCC/mk/rules.mk:217: build/rusefi.elf] Error 1
"make -j12 all" terminated with exit code 2. Build might be incomplete.
c++ -march=native -O3 -std=c++11 -o demo amalgamation_demo.cpp -I include/roaring/ -I /usr/local/openresty/luajit/include/luajit-2.1/
/tmp/ccU0wBoY.o: In function bindToLUA(lua_State*)': amalgamation_demo.cpp:(.text+0x3d5): undefined reference to
luaL_argerror'
amalgamation_demo.cpp:(.text+0x4c6): undefined reference to luaL_newmetatable' amalgamation_demo.cpp:(.text+0x4d3): undefined reference to
lua_pushvalue'
amalgamation_demo.cpp:(.text+0x4e5): undefined reference to lua_setfield' amalgamation_demo.cpp:(.text+0x4f7): undefined reference to
luaL_checkstack'
amalgamation_demo.cpp:(.text+0x514): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x523): undefined reference to
lua_pushcclosure'
amalgamation_demo.cpp:(.text+0x530): undefined reference to lua_settable' amalgamation_demo.cpp:(.text+0x54a): undefined reference to
lua_settop'
amalgamation_demo.cpp:(.text+0x557): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x5a1): undefined reference to
luaL_register'
amalgamation_demo.cpp:(.text+0x5ae): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x609): undefined reference to
luaL_register'
amalgamation_demo.cpp:(.text+0x616): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x62a): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x637): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x644): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0x680): undefined reference to lua_pushcclosure' amalgamation_demo.cpp:(.text+0x68d): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x69a): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x6ae): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x6bb): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x6c8): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0x6f7): undefined reference to lua_pushcclosure' amalgamation_demo.cpp:(.text+0x704): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x711): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x725): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x732): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x73f): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0x76e): undefined reference to lua_pushcclosure' amalgamation_demo.cpp:(.text+0x77b): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x788): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x79c): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x7a9): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x7b6): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0x7e5): undefined reference to lua_pushcclosure' amalgamation_demo.cpp:(.text+0x7f2): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x7ff): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x813): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x820): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x82d): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0x85c): undefined reference to lua_pushcclosure' amalgamation_demo.cpp:(.text+0x869): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x876): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x88a): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x897): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x8a4): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0x8ca): undefined reference to lua_pushcclosure' amalgamation_demo.cpp:(.text+0x8d7): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x8e4): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x8f8): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x905): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x912): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0x941): undefined reference to lua_pushcclosure' amalgamation_demo.cpp:(.text+0x94e): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x95b): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x96f): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x97c): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x989): undefined reference to
lua_pushstring'
amalgamation_demo.cpp:(.text+0x996): undefined reference to lua_settable' amalgamation_demo.cpp:(.text+0x9a3): undefined reference to
lua_settop'
amalgamation_demo.cpp:(.text+0xa3d): undefined reference to luaL_openlib' amalgamation_demo.cpp:(.text+0xa4f): undefined reference to
lua_pushinteger'
amalgamation_demo.cpp:(.text+0xa66): undefined reference to lua_setfield' amalgamation_demo.cpp:(.text+0xa9d): undefined reference to
luaL_openlib'
amalgamation_demo.cpp:(.text+0xaaf): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0xac6): undefined reference to
lua_setfield'
amalgamation_demo.cpp:(.text+0xcf1): undefined reference to luaL_openlib' amalgamation_demo.cpp:(.text+0xd0a): undefined reference to
lua_createtable'
amalgamation_demo.cpp:(.text+0xd37): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0xd51): undefined reference to
lua_rawseti'
amalgamation_demo.cpp:(.text+0xd71): undefined reference to lua_setfield' amalgamation_demo.cpp:(.text+0xdb3): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0xde4): undefined reference to luaL_openlib' amalgamation_demo.cpp:(.text+0xe26): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0xe5b): undefined reference to luaL_openlib' amalgamation_demo.cpp:(.text+0xe9d): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0xed2): undefined reference to luaL_openlib' amalgamation_demo.cpp:(.text+0xf14): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text+0xf49): undefined reference to luaL_openlib' amalgamation_demo.cpp:(.text+0xfcb): undefined reference to
luaL_openlib'
amalgamation_demo.cpp:(.text+0xfe0): undefined reference to lua_pushnumber' amalgamation_demo.cpp:(.text+0xff7): undefined reference to
lua_setfield'
amalgamation_demo.cpp:(.text+0x116f): undefined reference to luaL_argerror' amalgamation_demo.cpp:(.text+0x1254): undefined reference to
luaL_newmetatable'
amalgamation_demo.cpp:(.text+0x1261): undefined reference to lua_pushvalue' amalgamation_demo.cpp:(.text+0x1273): undefined reference to
lua_setfield'
amalgamation_demo.cpp:(.text+0x1285): undefined reference to luaL_checkstack' amalgamation_demo.cpp:(.text+0x12a4): undefined reference to
lua_pushstring'
amalgamation_demo.cpp:(.text+0x12b2): undefined reference to lua_pushcclosure' amalgamation_demo.cpp:(.text+0x12bf): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x12d9): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x12e6): undefined reference to
lua_settop'
amalgamation_demo.cpp:(.text+0x132a): undefined reference to luaL_register' amalgamation_demo.cpp:(.text+0x1337): undefined reference to
lua_settop'
amalgamation_demo.cpp:(.text+0x1379): undefined reference to luaL_register' amalgamation_demo.cpp:(.text+0x1386): undefined reference to
lua_settop'
amalgamation_demo.cpp:(.text+0x139a): undefined reference to lua_getfield' amalgamation_demo.cpp:(.text+0x13a7): undefined reference to
lua_pushstring'
amalgamation_demo.cpp:(.text+0x13b4): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x13c1): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x13ce): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x13e2): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text+0x13ef): undefined reference to lua_pushstring' amalgamation_demo.cpp:(.text+0x13fc): undefined reference to
lua_pushinteger'
amalgamation_demo.cpp:(.text+0x1409): undefined reference to lua_settable' amalgamation_demo.cpp:(.text+0x1416): undefined reference to
lua_settop'
amalgamation_demo.cpp:(.text+0x142a): undefined reference to lua_getfield' amalgamation_demo.cpp:(.text+0x1437): undefined reference to
lua_pushstring'
amalgamation_demo.cpp:(.text+0x1446): undefined reference to lua_pushinteger' amalgamation_demo.cpp:(.text+0x1453): undefined reference to
lua_settable'
amalgamation_demo.cpp:(.text+0x1460): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x15bb): undefined reference to
luaL_argerror'
amalgamation_demo.cpp:(.text+0x169e): undefined reference to luaL_argerror' amalgamation_demo.cpp:(.text+0x177e): undefined reference to
luaL_argerror'
amalgamation_demo.cpp:(.text+0x186a): undefined reference to luaL_argerror' amalgamation_demo.cpp:(.text+0x195a): undefined reference to
luaL_argerror'
/tmp/ccU0wBoY.o:amalgamation_demo.cpp:(.text+0x1a4a): more undefined references to luaL_argerror' follow /tmp/ccU0wBoY.o: In function
runLuaExample(lua_State*)':
amalgamation_demo.cpp:(.text+0x324f): undefined reference to luaL_loadbuffer' amalgamation_demo.cpp:(.text+0x3294): undefined reference to
lua_tolstring'
amalgamation_demo.cpp:(.text+0x32b2): undefined reference to lua_settop' amalgamation_demo.cpp:(.text+0x3864): undefined reference to
lua_pcall'
/tmp/ccU0wBoY.o: In function luaaa::LuaClass<int*>::LuaClass(lua_State*, std::string const&, luaL_Reg const*)::HelperClass::f__gc(lua_State*)': amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiEC1EP9lua_StateRKSsPK8luaL_RegEN11HelperClass5f__gcES4_[_ZZN5luaaa8LuaClassIPiEC1EP9lua_StateRKSsPK8luaL_RegEN11HelperClass5f__gcES4_]+0x11): undefined reference to
luaL_checkudata'
/tmp/ccU0wBoY.o: In function luaaa::LuaClass<int*>& luaaa::LuaClass<int*>::ctor<>(char const*)::HelperClass::f_new(lua_State*)': amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIEEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIEEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x32): undefined reference to
lua_newuserdata'
amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIEEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIEEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x4e): undefined reference to lua_getfield' amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIEEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIEEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x5b): undefined reference to
lua_setmetatable'
amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIEEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIEEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x7c): undefined reference to lua_pushnil' /tmp/ccU0wBoY.o: In function
luaaa::LuaClass<int*>& luaaa::LuaClass<int*>::ctor<int*>(char const*)::HelperClass::f_new(lua_State*)':
amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x48): undefined reference to lua_type' amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x57): undefined reference to
lua_touserdata'
amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x77): undefined reference to lua_newuserdata' amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x97): undefined reference to
lua_getfield'
amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0xa4): undefined reference to lua_setmetatable' amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0xc6): undefined reference to
luaL_checkudata'
amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0xe9): undefined reference to luaL_argerror' amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0xf6): undefined reference to
luaL_checkudata'
amalgamation_demo.cpp:(.text._ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State[_ZZN5luaaa8LuaClassIPiE4ctorIIS1_EEERS2_PKcEN11HelperClass5f_newEP9lua_State]+0x11c): undefined reference to `lua_pushnil'
Cloud we support overload functions:
myCat.def("eat", &&MyCat::eat)
myCat.def("eat", &&MyCat::eat2)
or
myCat.def("eat",
[](MyCat* cat, const std::string& some_thing) { return cat->eat(some_thing); }),
[](MyCat* cat, const Rat& rat) { return cat->eat(rat); }))
For static methods the same .fun calls?
#include "stdio.h"
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#include "luaaa.hpp"
void func0()
{
printf("func0\n");
}
void func1()
{
printf("func1\n");
}
std::string luaBehaviour = R"(
function foo(a, b)
return a - b
end
function update()
global_func0()
end
)";
int main(int argc, char** argv) {
lua_State* luaState = luaL_newstate();
auto globalModule = luaaa::LuaModule(luaState);
globalModule.fun("global_func0", func0);
int r = luaL_dostring(luaState, luaBehaviour.c_str());
if (r == LUA_OK)
{
lua_getglobal(luaState, "update");
if (lua_isfunction(luaState, -1))
{
lua_pcall(luaState, 0, 0, 0);
}
lua_getglobal(luaState, "foo");
if (lua_isfunction(luaState, -1))
{
lua_pushnumber(luaState, 5);
lua_pushnumber(luaState, 3);
lua_pcall(luaState, 2, 1, 0);
if (lua_isnumber(luaState, -1)) {
double result = lua_tonumber(luaState, -1);
printf("Lua Result: %f\n", result);
}
lua_pop(luaState, 1);
}
}
else
{
std::string errorMsg = lua_tostring(luaState, -1);
printf("Lua Error: %s\n", errorMsg.c_str());
}
return 0;
}
Hi!
Probably is my fault, but I was wondering if you had this problem before.
I just included luaaaa.h and added this line on a class: luaaa::LuaClass luaCat(mLuaState, "MyLuaComponent");
But when I compile I got link errors:
5>LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
5>CLua.lib(lauxlib.obj) : error LNK2001: unresolved external symbol __imp_freopen
5>CLua.lib(lauxlib.obj) : error LNK2001: unresolved external symbol __imp_ferror
5>CLua.lib(lauxlib.obj) : error LNK2001: unresolved external symbol __imp_feof
5>CLua.lib(lauxlib.obj) : error LNK2001: unresolved external symbol __imp_strerror
5>CLua.lib(lvm.obj) : error LNK2001: unresolved external symbol __imp_strcoll
Any help would be appreciated :)
Cheers!
Test code:
struct MyType
{
void myFunc(int, int);
};
LuaClass<MyType> myLuaClass(l, "myClass");
myLuaClass.fun("myFunc", &MyType::myFunc);
Produces this warning:
In file included from ./controllers/lua/lua_hooks.cpp:12:
./controllers/lua/luaaa/luaaa.hpp: In instantiation of 'static int luaaa::MemberFunctionCaller(void (TCLASS::*)(ARGS ...))::HelperClass::Invoke(lua_State*) [with TCLASS = configureRusefiLuaHooks(lua_State*)::MyType; ARGS = {int, int}; lua_State = lua_State]':
./controllers/lua/luaaa/luaaa.hpp:499:3: required from 'int (* luaaa::MemberFunctionCaller(void (TCLASS::*)(ARGS ...)))(lua_State*) [with TCLASS = configureRusefiLuaHooks(lua_State*)::MyType; ARGS = {int, int}; lua_CFunction = int (*)(lua_State*); lua_State = lua_State]'
./controllers/lua/luaaa/luaaa.hpp:641:50: required from 'luaaa::LuaClass< <template-parameter-1-1> >& luaaa::LuaClass< <template-parameter-1-1> >::fun(const char*, F) [with F = void (configureRusefiLuaHooks(lua_State*)::MyType::*)(int, int); TCLASS = configureRusefiLuaHooks(lua_State*)::MyType]'
./controllers/lua/lua_hooks.cpp:431:42: required from here
./controllers/lua/luaaa/luaaa.hpp:495:6: error: operation on 'idx' may be undefined [-Werror=sequence-point]
495 | (LuaStack<TCLASS>::get(state, 1).**(FTYPE*)(calleePtr))(LuaStack<ARGS>::get(state, idx--)...);
| ^
As you can see, this line in luaaa.hpp
is the issue:
(LuaStack<TCLASS>::get(state, 1).**(FTYPE*)(calleePtr))(LuaStack<ARGS>::get(state, idx--)...);
The list of arguments is evaluated one at a time via the parameter pack, then the arguments are passed to the underlying function. The problem is that in C++, it is undefined behavior to assign the same variable more than once between any two sequence points. The first sequence point is the previous line, and the next sequence point is the call to the function returned from LuaStack::get
, inbetween which idx
is assigned once for every argument passed.
PS: The fact that the commit 51ab2ef has different behavior for GCC vs. Clang vs. MSVC indicates that you're relying on undefined behavior that may not even be consistent within one particular compiler.
I have a C++ class I want to export to LUA. This class has a hashmap that maps a name to std::function
. Currently I typically put lamdba expressions in there.
I now want to allow LUA to add values to this hashmap. To experiment a little bit I modified the example.cpp to accept a std::function
with the same argument list in the testCallback function. This compiles fine but when I run this LUA complains:
lua err: [string "console"]:103: bad argument #1 to 'testCallback' (cpp class ``St8functionIFiRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEifEE`` not export)
Is it possible with luaaa to use std::function
instead of function pointers?
Line 1503 in 1654818
Sorry I'm not familiar with Lua API so I open a issue instead of sending a pull request.
如题
I've attempted to pull fresh luaaa (with our typeid fix) and things got pretty broken
https://github.com/rusefi/rusefi/runs/3705887714
Compiling histogram.cpp
In file included from ../firmware/controllers/lua/lua_hooks.cpp:12:
../firmware/controllers/lua/luaaa/luaaa.hpp:1058:18: error: declaration of template parameter ‘TCLASS’ shadows template parameter
1058 | template<typename TCLASS, bool> friend struct DestructorHelperClass;
| ^~~~~~~~
../firmware/controllers/lua/luaaa/luaaa.hpp:1055:12: note: template parameter ‘TCLASS’ declared here
1055 | template <typename TCLASS>
| ^~~~~~~~
../firmware/controllers/lua/luaaa/luaaa.hpp:1320:86: error: ‘nullptr_t’ has not been declared
1320 | inline LuaClass<TCLASS>& ctor(const char * name, TCLASS*(*spawner)(ARGS...), nullptr_t) {
| ^~~~~~~~~
../firmware/controllers/lua/luaaa/luaaa.hpp:1408:92: error: ‘nullptr_t’ has not been declared
1408 | inline LuaClass<TCLASS>& ctor(const std::string& name, TCLASS*(*spawner)(ARGS...), nullptr_t) {
| ^~~~~~~~~
../firmware/controllers/lua/luaaa/luaaa.hpp: In member function ‘luaaa::LuaClass< <template-parameter-1-1> >& luaaa::LuaClass< <template-parameter-1-1> >::ctor(const string&, TCLASS* (*)(ARGS ...))’:
../firmware/controllers/lua/luaaa/luaaa.hpp:1399:25: error: ‘F’ was not declared in this scope
1399 | return ctor<F>(name.c_str(), spawner);
| ^
../firmware/controllers/lua/luaaa/luaaa.hpp: In member function ‘luaaa::LuaClass< <template-parameter-1-1> >& luaaa::LuaClass< <template-parameter-1-1> >::ctor(const string&, TCLASS* (*)(ARGS ...), TRET (*)(TCLASS*))’:
../firmware/controllers/lua/luaaa/luaaa.hpp:1404:25: error: ‘F’ was not declared in this scope
1404 | return ctor<F, D>(name.c_str(), spawner, deleter);
| ^
../firmware/controllers/lua/luaaa/luaaa.hpp:1404:28: error: ‘D’ was not declared in this scope
1404 | return ctor<F, D>(name.c_str(), spawner, deleter);
| ^
../firmware/controllers/lua/luaaa/luaaa.hpp: In member function ‘luaaa::LuaClass< <template-parameter-1-1> >& luaaa::LuaClass< <template-parameter-1-1> >::ctor(const string&, TCLASS* (*)(ARGS ...), int)’:
../firmware/controllers/lua/luaaa/luaaa.hpp:1409:25: error: ‘F’ was not declared in this scope
1409 | return ctor<F, D>(name.c_str(), spawner, nullptr);
| ^
../firmware/controllers/lua/luaaa/luaaa.hpp:1409:28: error: ‘D’ was not declared in this scope
1409 | return ctor<F, D>(name.c_str(), spawner, nullptr);
| ^
../firmware/controllers/lua/lua_hooks.cpp: In function ‘int lua_readpin(lua_State*)’:
../firmware/controllers/lua/lua_hooks.cpp:27:7: warning: unused variable ‘msg’ [-Wunused-variable]
27 | auto msg = luaL_checkstring(l, 1);
| ^~~
make: *** [../firmware/ChibiOS/os/common/startup/SIMIA32/compilers/GCC/rules.mk:130: build/obj/lua_hooks.o] Error 1
make: *** Waiting for unfinished jobs....
Simulator compilation failed
My IDE is showing ~23 errors
Quite a few of them are 'cacheLuaState' may be undeclared or unknown.
And the rest come from template errors:
with
[
V=int Player::* ,
T=int Player::*
]
and
[
V=int Player::*
]
and
[
T=int Player::*
]
F:\Dev\CPP\untitled3\luaaa.hpp(1440): note: There is no context in which this conversion is possible
F:\Dev\CPP\untitled3\luaaa.hpp(221): note: see declaration of 'luaaa::LuaStack<V>::put'
with
[
V=int Player::*
]
F:\Dev\CPP\untitled3\main.cpp(26): note: see reference to function template instantiation 'luaaa::LuaClass<Player> &luaaa::LuaClass<Player>::def<intPlayer::* >(const char *,const V &)' being compiled
with
[
V=int Player::*
]
F:\Dev\CPP\untitled3\main.cpp(28): note: see reference to function template instantiation 'luaaa::LuaClass<Player> &luaaa::LuaClass<Player>::def<intPlayer::* >(const char *,const V &)' being compiled
with
[
V=int Player::*
]```
When using the class binding functions, it appears that once a class has been bound to a lua_State, another lua_State cannot also have access to the given class while the first lua_State still exists.
As a minimal display of the issue, referencing the Cat class from your example code:
lua_State* state1 = luaL_newstate();
lua_State* state2 = luaL_newstate();
luaaa::LuaClass<Cat> lc1(state1, "AwesomeCat");
lc1.ctor();
luaaa::LuaClass<Cat> lc2(state2, "AwesomeCat");
lc2.ctor();
lua_close(state1);
lua_close(state2);
Results in the following assertion failure:
luaaa.hpp:979: luaaa::LuaClass< <template-parameter-1-1> >::LuaClass(lua_State*, const char*, const luaL_Reg*) [with TCLASS = Cat; lua_State = lua_State; luaL_Reg = luaL_Reg]: Assertion `klassName == nullptr' failed.
Meanwhile, if you close the first state before proceeding to the second, there isn't a problem.
lua_State* state1 = luaL_newstate();
lua_State* state2 = luaL_newstate();
luaaa::LuaClass<Cat> lc1(state1, "AwesomeCat");
lc1.ctor();
lua_close(state1);
luaaa::LuaClass<Cat> lc2(state2, "AwesomeCat");
lc2.ctor();
lua_close(state2);
Using LuaModule in this way does not appear to have the same issue.
class MyClass {
public:
MyClass(lua_State* l) {
luaL_error(l, "first constructor called");
}
MyClass(lua_State* l, int x) {
if (x > 100) {
luaL_error(l, "oops, X too large!");
}
}
}
.......
LuaClass<MyClass> myClass(l, "myClass");
// These both compile
myClass.ctor<lua_State*>();
myClass.ctor<lua_State*, int>();
then you have the lua
local obj1 = myClass.new() -- works, passes lua state properly
local obj = myClass.new(200) -- doesn't work, causes runtime error!
The second one causes:
bad argument #2 to 'new' (string expected, got userdata)
The problem is that LuaStack<lua_State*>::get()
correctly just returns the lua state, but it causes the indices to be wrong for all following parameters, since it doesn't actually occupy a spot on the stack like all other args do.
See https://github.com/rusefi/rusefi/pull/4391/files# for our solution, adding a specialization to PlacementConstructorCaller
when the first parameter is a lua_State*
, and passing it directly instead of relying on the LuaStack<lua_State*>::get()
function (maybe this one shouldn't even exist, as the ignored idx parameter is in fact the root of this bug?).
g++-13 -std=c++11 example.cpp -I/usr/include/lua5.4
In file included from example.cpp:9:
../luaaa.hpp: In member function ‘luaaa::LuaModule& luaaa::LuaModule::def(const char*, const luaaa::LuaClass<TCLASS, TAG>&, const TCLASS*, void (*)(TCLASS*))’:
../luaaa.hpp:1681:13: error: need ‘typename’ before ‘luaaa::LuaClass<TCLASS, TAG>::UserDataDetail’ because ‘luaaa::LuaClass<TCLASS, TAG>’ is a dependent scope
1681 | LuaClass<TCLASS, TAG>::UserDataDetail userData;
| ^~~~~~~~~~~~~~~~~~~~~
../luaaa.hpp:1681:51: error: expected ‘;’ before ‘userData’
1681 | LuaClass<TCLASS, TAG>::UserDataDetail userData;
| ^~~~~~~~
../luaaa.hpp:1684:17: error: ‘userData’ was not declared in this scope
1684 | userData.obj = const_cast<TCLASS*>(obj);
| ^~~~~~~~
../luaaa.hpp:1690:66: error: ‘luaaa::LuaClass<TCLASS, TAG>::UserDataDetail’ is not a type
1690 | static int f_dtor(LuaClass<TCLASS, TAG>::UserDataDetail* uData) {
| ^~~~~~~~~~~~~~
../luaaa.hpp: In static member function ‘static int luaaa::LuaModule::def(const char*, const luaaa::LuaClass<TCLASS, TAG>&, const TCLASS*, void (*)(TCLASS*))::HelperClass::f_dtor(int*)’:
../luaaa.hpp:1691:49: error: request for member ‘obj’ in ‘uData->’, which is of non-class type ‘int’
1691 | if (uData && uData->obj && uData->free_func)
| ^~~
../luaaa.hpp:1691:63: error: request for member ‘free_func’ in ‘uData->’, which is of non-class type ‘int’
1691 | if (uData && uData->obj && uData->free_func)
| ^~~~~~~~~
../luaaa.hpp:1693:56: error: request for member ‘free_func’ in ‘uData->’, which is of non-class type ‘int’
1693 | ((DELETERFTYPE)(uData->free_func))(uData->obj);
| ^~~~~~~~~
../luaaa.hpp:1693:75: error: request for member ‘obj’ in ‘uData->’, which is of non-class type ‘int’
1693 | ((DELETERFTYPE)(uData->free_func))(uData->obj);
| ^~~
../luaaa.hpp:1694:40: error: request for member ‘obj’ in ‘uData->’, which is of non-class type ‘int’
1694 | uData->obj = nullptr;
| ^~~
../luaaa.hpp: In member function ‘luaaa::LuaModule& luaaa::LuaModule::def(const char*, const luaaa::LuaClass<TCLASS, TAG>&, const TCLASS*, void (*)(TCLASS*))’:
../luaaa.hpp:1713:62: error: ‘luaaa::LuaClass<TCLASS, TAG>::UserDataDetail’ is not a type
1713 | static int f_dtor(LuaClass<TCLASS, TAG>::UserDataDetail* uData)
| ^~~~~~~~~~~~~~
../luaaa.hpp: In static member function ‘static int luaaa::LuaModule::def(const char*, const luaaa::LuaClass<TCLASS, TAG>&, const TCLASS*, void (*)(TCLASS*))::HelperClass::f_dtor(int*)’:
../luaaa.hpp:1715:45: error: request for member ‘obj’ in ‘uData->’, which is of non-class type ‘int’
1715 | if (uData && uData->obj)
| ^~~
../luaaa.hpp:1717:43: error: request for member ‘obj’ in ‘uData->’, which is of non-class type ‘int’
1717 | delete uData->obj;
| ^~~
../luaaa.hpp:1718:36: error: request for member ‘obj’ in ‘uData->’, which is of non-class type ‘int’
1718 | uData->obj = nullptr;
| ^~~
../luaaa.hpp: In member function ‘luaaa::LuaModule& luaaa::LuaModule::def(const char*, const luaaa::LuaClass<TCLASS, TAG>&, const TCLASS*, void (*)(TCLASS*))’:
../luaaa.hpp:1723:17: error: ‘userData’ was not declared in this scope
1723 | userData.obj = new TCLASS;
| ^~~~~~~~
../luaaa.hpp:1735:65: error: expected primary-expression before ‘)’ token
1735 | auto uData = (LuaClass<TCLASS, TAG>::UserDataDetail*)lua_newuserdata(m_state, sizeof(LuaClass<TCLASS, TAG>::UserDataDetail));
| ^
In file included from ../luaaa.hpp:27:
/usr/include/lua5.4/lua.h:423:33: error: expected ‘,’ or ‘;’ before ‘lua_newuserdatauv’
423 | #define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1)
| ^~~~~~~~~~~~~~~~~
../luaaa.hpp:1735:66: note: in expansion of macro ‘lua_newuserdata’
1735 | auto uData = (LuaClass<TCLASS, TAG>::UserDataDetail*)lua_newuserdata(m_state, sizeof(LuaClass<TCLASS, TAG>::UserDataDetail));
| ^~~~~~~~~~~~~~~
../luaaa.hpp:1743:30: error: ‘userData’ was not declared in this scope; did you mean ‘uData’?
1743 | uData->obj = userData.obj;
| ^~~~~~~~
| uData
../luaaa.hpp: In instantiation of ‘luaaa::LuaModule& luaaa::LuaModule::def(const char*, const luaaa::LuaClass<TCLASS, TAG>&, const TCLASS*, void (*)(TCLASS*)) [with TCLASS = Cat; int TAG = 0]’:
example.cpp:352:19: required from here
../luaaa.hpp:1681:36: error: dependent-name ‘luaaa::LuaClass<TCLASS, TAG>::UserDataDetail’ is parsed as a non-type, but instantiation yields a type
1681 | LuaClass<TCLASS, TAG>::UserDataDetail userData;
| ^~~~~~~~~~~~~~
../luaaa.hpp:1681:36: note: say ‘typename luaaa::LuaClass<TCLASS, TAG>::UserDataDetail’ if a type is meant
../luaaa.hpp:1735:50: error: dependent-name ‘luaaa::LuaClass<TCLASS, TAG>::UserDataDetail’ is parsed as a non-type, but instantiation yields a type
1735 | auto uData = (LuaClass<TCLASS, TAG>::UserDataDetail*)lua_newuserdata(m_state, sizeof(LuaClass<TCLASS, TAG>::UserDataDetail));
| ^~~~~~~~~~~~~~
../luaaa.hpp:1735:50: note: say ‘typename luaaa::LuaClass<TCLASS, TAG>::UserDataDetail’ if a type is meant
I have a C++DLL file that I want to register the get type function to the Lua virtual machine. However, the get method needs to return the function execution value and also the obtained value. So, how do I handle these multiple return values? Can I use this template to register to the Lua virtual machine
@mck1117 why exactly do we not have typeid(T) available in https://github.com/rusefi/rusefi?
Anyway we do not have typeid(T)
it would be nice to have an option not to require typeid(T)
see rusefi current solution rusefi@cacdd76
I try to wrap my cpp functions (Qt and native) via luaaa.
Build it with cmake and get libluabridge.so library, wich uses luaaa.hpp.
Then I try to run simple script and get an error:
main.lua
require 'libluabridge';
error
$ LD_LIBRARY_PATH=:../lib:../../3rdparty/lib/ lua -i main.lua
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
lua: error loading module 'libluabridge' from file './libluabridge.so':
./libluabridge.so: undefined symbol: luaopen_libluabridge
stack traceback:
[C]: ?
[C]: in function 'require'
main.lua:1: in main chunk
[C]: ?
$
Heed help! Pls!
struct MyCat {
int Age;
};
void bindToLUA(lua_State * L)
{
LuaClass<MyCat> myCat(L, "MyCat");
myCat.ctor();
myCat.def("Age", &MyCat::Age);
I'm trying to make a c++ lua 5.1 package and I cant seem to find out how to get any class exported.
I've tried setting it from "luaopen_test", tried returning it from a normally exported function in luaL_reg array for export like how you would call `require('test').new()' but i cant get a return when i do. only lua_push funcs work in returning anything.
both LuaClass and LuaModule have no effect.
My use case is similar to below.
int test_add1(lua_State *L) {
double d = luaL_checknumber(L, 1); // get item 1
lua_pushnumber(L, d + 1);
return 1; // number of items returned
}
static const struct luaL_reg testlib[] = {
{"add1", test_add1},
{NULL, NULL}
};
extern "C"
int luaopen_test (lua_State *L) {
luaL_register(L, "test", testlib);
return 1;
}
Using gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) on centos 7 the compliler complains about missing typename.
Adding typename where the compiler suggests fixes the issue and allows the example to compile and run.
$ git diff
diff --git a/luaaa.hpp b/luaaa.hpp
index d8cdc86..7b112fa 100644
--- a/luaaa.hpp
+++ b/luaaa.hpp
@@ -2523,7 +2523,7 @@ namespace LUAAA_NS
#else
luaL_Reg regtab = { nullptr, nullptr };
luaL_openlib(m_state, m_moduleName, ®tab, 0);
- auto uData = (LuaClass<TCLASS, TAG>::UserDataDetail*)lua_newuserdata(m_state, sizeof(LuaClass<TCLASS, TAG>::UserDataDetail));
+ auto uData = (typename LuaClass<TCLASS, TAG>::UserDataDetail*)lua_newuserdata(m_state, sizeof(typename LuaClass<TCLASS, TAG>::UserDataDetail));^M
if (uData)
{
uData->obj = userData.obj;
I created a AUR package for this project for easier accessibility for arch linux users.
it puts the header file in your /usr/include
directory.
here's the link: https://aur.archlinux.org/packages/luaaa-git
Hi! The library is very useful, but what about binding existing C++ objects (instances of classes) to lua? Is there any solutions for this?
This code will cause an assertion failure on the second test:
void test1()
{
lua_State* l = make_lua();
LuaClass<MyType> myLuaType(l, "MyType");
// ... do stuff ...
destroy_lua(l);
}
void test2()
{
lua_State* l = make_lua();
LuaClass<MyType> myLuaType(l, "MyType");
// ... do stuff ...
destroy_lua(l);
}
The assertion in the LuaClass
constructor is currently too strict. Seeing if the same string is already there would likely be more appropriate.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.