Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Making a Lua binding, questions  (Read 4370 times)

0 Members and 1 Guest are viewing this topic.

Mjonir

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Making a Lua binding, questions
« on: June 06, 2012, 06:47:44 am »
Hi,

For my game engine, I'm preparing a sort of Lua binding so that the scripter will be able to create and manipulate SFML objects directly.

I don't have much time at the moment and only started recently so it cannot do much yet, but here's a Windows executable version of the canonical demo translated in Lua: Download link.


What brings me here is a problem I encountered when trying to bind sf::Window, and more specifically its sf::Window(WindowHandle, const ContextSettings&) constructor. The problem here is WindowHandle, which gives me a compile-time error:

Code: [Select]
error: invalid use of incomplete type 'struct HWND__'
Looking a bit at the code of WindowHandle.hpp I tried to define _WIN32, but it didn't solve the problem. I'm not sure where to go from here, any hint Laurent? :)


Also as you can see, apart from constructors all functions calls have to be explicit (no support for default arguments). I think the only solution is to decompose all functions with default values to overloaded functions. I'd also like to define a getType() static member function for all SFML classes to do some dynamic typechecking and yield better error messages.

Since I'd like to avoid modifying the SFML source for obvious maintenance reasons, I'm thinking of creating a wrapper class for each SFML class that would inherit publicly and declare these new member functions. It'll be quite a bit of work though, so I'm wondering if anyone has got a better idea on how to do that before it's too late? :P


Thanks in advance!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Making a Lua binding, questions
« Reply #1 on: June 06, 2012, 08:17:48 am »
Quote
error: invalid use of incomplete type 'struct HWND__'
WindowHandle is an opaque pointer on Windows, that you just need to pass around. You're not supposed to "use" (dereference) it. Can you show your code?

Quote
Since I'd like to avoid modifying the SFML source for obvious maintenance reasons, I'm thinking of creating a wrapper class for each SFML class that would inherit publicly and declare these new member functions.
Why don't you use a wrapper library such as luabind, which allows you to declare the binding in a very simple way?
Laurent Gomila - SFML developer

Mjonir

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: Making a Lua binding, questions
« Reply #2 on: June 06, 2012, 09:18:04 am »
WindowHandle is an opaque pointer on Windows, that you just need to pass around. You're not supposed to "use" (dereference) it. Can you show your code?

Here it is, it's a complete WIP though :)

See commented lines at binding/lua_registration_SFML_window.cpp:123, 126 and 146. I'm not sure what happens behind this though, it's all deep magic for me. If it helps, compiler errors on that line:

template <class T>
class_id const registered_class<T>::id = allocate_class_id(typeid(T));

With T = HWND__ I think. It looks like luabind needs to know.

Quote
Why don't you use a wrapper library such as luabind, which allows you to declare the binding in a very simple way?

I'm actually using luabind! :)

luabind v0.9.1 (latest) doesn't allow default values for parameters (was apparently scheduled for v1, but the project is not really maintained anymore). I've Googled it and the only solution seems to be function overloading.

Forget what I said about public inheritance though, I realized that in this case (since I'm not accessing anything private) I can just make static functions for each overload that accept a pointer to that SFML class and then bind them as if they came from the class. It'll be cleaner and easier even if not ideal. Still need to implement all these overloads though ^^'


Other problems I encountered with luabind were:

- No support for class attributes, I will probably have to wrap them all in static member functions. Maybe I can inject them again in their classes as attributes once luabind has finished.
- No support for operator[], which is really annoying! I think I'll just bind it to the __call metamethod in Lua, which is the equivalent of operator(), for the moment. Perhaps I can find a workaround using the Lua C API or something on the Lua side, I don't know yet :(
« Last Edit: June 06, 2012, 09:25:38 am by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Making a Lua binding, questions
« Reply #3 on: June 06, 2012, 09:29:51 am »
Googling "luabind opaque pointer" gives interesting results.

This one seems to have a solution:
http://osdir.com/ml/lang.lua.bind.user/2003-11/msg00013.html
Laurent Gomila - SFML developer

Mjonir

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: Making a Lua binding, questions
« Reply #4 on: June 06, 2012, 11:05:39 am »
Weird... After a lot of testing I got it to compile (not tested yet) using this technique if and only if the binding of WindowHandler + Window is done and implemented in the file where I initialize Lua. If it's in any other file, the error reappears. I'll have to understand why before I move further.

I expect I should be able to work on this binding and release it this summer.

Thanks a lot for the extremely fast help as usual :)

Mjonir

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: Making a Lua binding, questions
« Reply #5 on: June 07, 2012, 01:19:39 am »
Yay, I finally found out what makes it work! It took me hours of testing to isolate the cause as the behaviour seemed totally random.

To sum it up:
  • In general, no matter how I did it, compilation will crash when binding something with sf::WindowHandle, the trick mentioned in the link didn't seem to work.
  • It turns out that by great luck,  I tried binding the window in a file that included "Window.h" for completely unrelated reasons, and it worked!
  • I put everything back how it was and just included "Windows.h" in the file for window binding, and it worked as well.
To have it work in Lua, I also had to bind this:
luabind::scope register_WindowHandle()
{
    #ifdef BUILD_WINDOWS
    return
    class_<HWND__>("HWND__")
        ;
    #endif
}

and NOT sf::WindowHandle.


Here are updated, working sources: Download link

(By the way main.cpp in the previous archive was obviously the wrong one, sorry for that ^^')


Window executable demo using the handle at main.lua:21 and 22. The window "stops responding" however, not sure if that's normal behaviour or not as I've never played with these functions before.


It's really annoying that I'd have to make the binding OS-specific though, and it looks like it's going to bring lots of problems. Maybe it's better if I left it out of the binding, or only include it with a compilation option? :/