Wrapper Function for lua_register?

Started by
5 comments, last by BitMaster 7 years, 11 months ago

Hi,

Trying to write a wrapper for a lua virtual machine object that will register functions but am having trouble passing a function pointer parameter to it.

The idea is to pass something like, "Foo.Go" to RegisterFunction and that will associated it with the lua_state member of the virtual machine class.

This is what i have:


void LuaVM::RegisterFunction(const char* name, lua_CFunction functionName) 
{	
	lua_register(getState(), name, functionName);
}

I'm getting the error: "a nonstatic member reference must be relative to a specific object", Any ideas on how to tackle this?

Advertisement

A quick google search turned up this: http://stackoverflow.com/questions/32416388/how-to-register-member-function-to-lua-without-lua-bind-in-c

Might be handy?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This has nothing to do with the Lua registry. Or even Lua.

A member function (that is, a non-static function in a class or struct) is fundamentally different from a free function. A free function (often called a C function) can interact very simply with C code. A member function cannot.

Lua is written in C and thus cannot interact interact with C++ (there is no well-defined C++ ABI and as such 'calling a member function' is an unsolvable problem because different C++ compilers have very different idea what exactly that means and how to do that).

The link ApochPiQ posted will certainly help with part of your problem ('how do I write glue code to deal with that'). It does not seem to go into much detail beyond that and it opens a whole can of worms about 'why do I have to do that at all?' (for a few basic keywords to start your search, see above) as well as where to store the this-pointer as well as questions about the lifetime and ownership of this between C++ and Lua from then on.

It would have been a better idea to post this in For Beginners since that would have obligated people to be a bit more verbose in their answers (I don't have the time now, though). I would also advise you to take a step back from Lua for the moment and deal with the issues raised here in a pure C++ world for now. It's not horribly difficult but you will need to spend some time there to get a feeling for the area and Lua just adds additional complications on top of that.

Lua is written in C and thus cannot interact interact with C++ (there is no well-defined C++ ABI and as such 'calling a member function' is an unsolvable problem because different C++ compilers have very different idea what exactly that means and how to do that).

Lua is written to be capable of building in C or C++, and it is distributed as source code, so it doesn't need a well-defined ABI to interact with other C++ code. You can build it to match however you're building the rest of your code.

Certainly true, but it is usually distributed and often used as a dynamic library.

Sure, if you link it statically as part of your customized build, a lot of things go (same goes for a lot of other projects), but not right out of the box (teaching Lua to deal with member function pointers feels like a decidedly non-trivial change and still leaves the whole 'who deals with this and lifetime and ownership?'-issue floating around). And any change you do there could become very annoying when you need to upgrade to a new Lua version. I would not do that myself, least of all advise someone markedly newer to try it.

Also, "capable of building in C++" sounds a bit grander in my mind than it really is. It has a very basic support to avoid C++ name mangling and some macro hackery to switch between exceptions and setjmp/longjmp.

There is a lot of "you could of course also..." in that whole area but considering the OP was confused by the member function/free function issue already I did not consider it useful to open those can of worms. They are best left for after you gained a few skill points.

Certainly true, but it is usually distributed and often used as a dynamic library.

Sure, if you link it statically as part of your customized build, a lot of things go (same goes for a lot of other projects), but not right out of the box (teaching Lua to deal with member function pointers feels like a decidedly non-trivial change and still leaves the whole 'who deals with this and lifetime and ownership?'-issue floating around). And any change you do there could become very annoying when you need to upgrade to a new Lua version. I would not do that myself, least of all advise someone markedly newer to try it.

Also, "capable of building in C++" sounds a bit grander in my mind than it really is. It has a very basic support to avoid C++ name mangling and some macro hackery to switch between exceptions and setjmp/longjmp.

There is a lot of "you could of course also..." in that whole area but considering the OP was confused by the member function/free function issue already I did not consider it useful to open those can of worms. They are best left for after you gained a few skill points.

The macro to use exceptions is what allows you to do things like actually use a C++ class in code that is meant to be called from Lua, allowing you do do things like check for valid input and throw Lua errors while still cleaning up your stack. It might seem small, but it's the difference between able to safely write normal C++ style code or being stuck writing C style code with Lua. Your whole point was that you cannot interface between the two. That "macro hackery" is there to be able to do it.

When I downloaded Lua myself, I just threw the code in a static library and built it. I wasn't even really aware of what else I should try. It's probably more common than you think that other people did the same thing.

"Lua is written in C and thus cannot interact interact with C++" - You seem capable enough to be able to come up with plenty of examples of things written in C that interact with other things written in C++, so this is clearly false. I could name a bunch of stuff statically linked together, and then get into dynamic linking, and then what about inter-process communication? Distributed applications? The Internet? Interact is a broad term. I actually don't think I've ever worked on anything substantial that was pure C or pure C++. Everything has had some of both.

Yes, you wouldn't hand a member function pointer to Lua, because in general, in C++, a member function pointer is a worthless thing to pass around, because it's too specific. The type of the class is part of its type. It doesn't matter whether Lua is pure C or if it was an idiomatic C++ object-oriented-designed interpreter, it still almost certainly wouldn't have an interface to use with your member function pointer. Saying the reason it cannot do it is because it's C is misleading and wrong.

I still agree that the OP does appear to be ready to tackle writing a language binding at this time. However, someone else might be reading this.

The macro to use exceptions is what allows you to do things like actually use a C++ class in code that is meant to be called from Lua, allowing you do do things like check for valid input and throw Lua errors while still cleaning up your stack. It might seem small, but it's the difference between able to safely write normal C++ style code or being stuck writing C style code with Lua. Your whole point was that you cannot interface between the two. That "macro hackery" is there to be able to do it.

Lua uses some purely internal macros (triggered when you use a C++ compiler to build it) to have a basic interaction with C++ exceptions, yes. However, for some other reasons (especially in the area of game development) the usefulness of that is severely restricted.
First, in our domain exceptions (whether to use them at all, or not) is a topic of hot debate. There is quite a few people (especially among the professionals) who argue most strictly against them. I don't follow that line, by the way.
That said, even if you use exceptions you do not need to compile Lua as C++ code. Make your calls into Lua as pcalls (or set your own error handler) and make sure your C++ code cannot throw into Lua (should be trivial by placing an adequate try/catch->luaError block in your automatic glue templates). You could of course ask: Why go through that? Here is the thing: although Lua can interact with C++ exceptions after a bit of persuasion, LuaJIT cannot. If you are using it or want the option for the future, you better stick to the no-exception-way.

When I downloaded Lua myself, I just threw the code in a static library and built it. I wasn't even really aware of what else I should try. It's probably more common than you think that other people did the same thing.

I like building my stuff as a single executable as well. However, building Lua as C++ does not solve the problem. You now have Lua and the rest of your code using the same ABI (provided there are no important differences in how you compile the individual static libraries being linked). They still talk to each other using a C API. Sure, you can extend that API (you have the source, after all) but at that point it stops being Lua and is BitLua, PinkLua or unnamed-largely-compatible-Lua-fork. You cannot just replace it with a new version or different fork. The Lua developers won't add a C++ interface because the ABI thing would be a huge issue for everyone not using static linkage by default (or even sticks to simply downloading the DLL).

"[background=#fafbfc]Lua is written in C and thus cannot interact interact with C++[/background]
" - You seem capable enough to be able to come up with plenty of examples of things written in C that interact with other things written in C++, so this is clearly false. I could name a bunch of stuff statically linked together, and then get into dynamic linking, and then what about inter-process communication? Distributed applications? The Internet? Interact is a broad term. I actually don't think I've ever worked on anything substantial that was pure C or pure C++. Everything has had some of both.

The statement was written for someone who was in well over his depth and thinking they had a Lua problem while they had a fundamental parts of the language problem. ApochPiQ technically solved it but in my opinion the that was insufficient to make the OP realize the pit they are in. When writing the post I did have the issue expanding to several paragraphs but I found covering all bits I would need to touch would take much more time than I could give at that time. So I instead went for a shortcut (especially since all of this would go over the OPs head at this point) which mentions the important keywords to start your own search for enlightenment. It's a convenient lie, yes, and I think we have expanded on that by now.
In my mind the post was in For Beginners and I considered it worse to open completely useless (at this point in time) tangents for the OP.

Yes, you wouldn't hand a member function pointer to Lua, because in general, in C++, a member function pointer is a worthless thing to pass around, because it's too specific. The type of the class is part of its type. It doesn't matter whether Lua is pure C or if it was an idiomatic C++ object-oriented-designed interpreter, it still almost certainly wouldn't have an interface to use with your member function pointer. Saying the reason it cannot do it is because it's C is misleading and wrong.

I still maintain it is because of the C++ ABI. The ABI is a mess to deal with, a huge one. Even projects which are internally implemented in C++ sometimes pipe themselves through a pure C API because there is no good, general solution.
If there were some common ground of C++ ABI you could rely on, I see no reason why there could not be some quick luaL-utility-functions to deal with the issue (after all, there are already several luaL-functions which you strictly don't need but which help your quality of life in the general case.

This topic is closed to new replies.

Advertisement