decimad / luabind-deboostified

Create Lua bindings for your C++ code easily - my improvements
http://www.vrac.iastate.edu/vancegroup/docs/luabind/
Other
70 stars 27 forks source link

Lua classes from C++ #35

Closed osaengine closed 7 years ago

osaengine commented 7 years ago

-

decimad commented 7 years ago

Hi! I need a small repro. Can you assist me with that?

decimad commented 7 years ago

Although, given the stacktrace, I suppose you're trying to pass a member function pointer. I'm not aware of a technical solution in the library that would allow such. If that is the case it would be wise to explecitly disallow it though through compile time checks.

osaengine commented 7 years ago

Yes, I try to invoke method of some class. Seems it is impossible in Luabind. Or I've missed something?

decimad commented 7 years ago

The problem is not to invoke a method of some class, but passing a member function pointer, I believe. We'd need to add overloads/converters and add each different signature of member function pointer in use to a true value type, so it can be stored correctly and "decoded" again. Member function pointers cannot be treated like ordinary pointers. But maybe I'm totally mistaken... I'm just thinking out loud.

osaengine commented 7 years ago

Actually the issue appears while regular method call. Like

call_function(state, "Close");

So the issue not in function pointer. Issue with instance of Lua class.

decimad commented 7 years ago

Well, this would qualify as bug.

decimad commented 7 years ago

The only code of you I see is "call_function(state, "SetUpdateCallback", &MyHandler::OnUpdate);" which is not a member function call, right? It calls the free function SetUpdateCallback with a member function parameter. call_function(state, "Close") is not a member function call either, it calls a global function "Close". Please provide more context.

luabind-deboostified passes the free function tests contained. If you can provide a minimal example that fails, I could do more.

osaengine commented 7 years ago

Did a migration on deboostified. Looks the issue still is. Here is the latest stack trace:

System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception.
   at _CxxThrowException(Void* , _s__ThrowInfo* )
   at luabind.detail.call_error(lua_State* L) in c:\luabind\detail\call_shared.hpp:line 32
   at luabind.detail.call_function_struct<luabind::adl::object,luabind::meta::type_list<>,luabind::meta::index_list<1>,1,&luabind::detail::pcall,0>.call<char const (&)[6]>(object* , lua_State* L, $ArrayType$$$BY05$$CBD* <args_0>) in c:\luabind\detail\call_function.hpp:line 125
   at luabind.call_pushed_function<class luabind::adl::object,struct luabind::meta::type_list<>,char const (&)[6]>(object* , lua_State* L, $ArrayType$$$BY05$$CBD* <args_0>) in c:\uabind\detail\call_function.hpp:line 147
   at luabind.call_function<class luabind::adl::object,struct luabind::meta::type_list<>,char const (&)[6]>(object* , object* obj, $ArrayType$$$BY05$$CBD* <args_0>)

Line is

auto state = call_function(ls, "CreateDataSource", str1, str2, (int)paramEx); call_function(state, "Close"); // <--- this line cause an error

osaengine commented 7 years ago

Lua's equivalent (that is works fine):

state1 = CreateDataSource("TQBR", "LKOH", INTERVAL_M1); --state1:SetUpdateCallback(NewCandle); state1:Close();

decimad commented 7 years ago

call_function expects a lua state or a callable "function" object as its first argument, neither of which is the case for your call. Maybe try call_function(state["Close"])? I did not test it, but it should push a lua function and call it.

decimad commented 7 years ago

And you could pass in a std::function as a callback function, for your seconds problem.

osaengine commented 7 years ago

call_function(state["Close"]) helped! Thanks.

Could you please provide an example? My code below. What I should to change?

decimad commented 7 years ago

bool result = call_function(state["SetCallback"], state, std::function<void(int)>(&DataHandler::OnUpdate, this));

might work depending on your circumstances.

decimad commented 7 years ago

I'm thinking about maybe adding a convenience syntax for member function calls should be added, in case I did not overlook anything that is in place already.

decimad commented 7 years ago

ermm, it'd be std::bind(&DataHandler::OnUpdate, this, std::placeholders::_1) or something... I'm not close to a compiler currently^^

osaengine commented 7 years ago

Wrote following, but issue still is:

decimad commented 7 years ago

std::function<void(int)> handler = std::bind(&DataHandler::OnUpdate, this, std::placeholders::_1);

Also remember that the lua function will probably expect the "state" as first arg and only then the callback, if it is a "well behaved" member function.

decimad commented 7 years ago

or alternatively with lambdas

std::function<void(int)> = [&](int foo) { OnUpdate(foo); }

osaengine commented 7 years ago

Same issue. Stack trace:

at _CxxThrowException(Void , _s__ThrowInfo ) at luabind.detail.make_pointer_instance<class std::function<void cdecl(int)> >(lua_State L, function<void __cdecl(int)>* p) in c:\luabind\detail\make_instance.hpp:line 72 at luabind.detail.make_pointee_instance<class std::function<void cdecl(int)> &>(lua_State L, function<void __cdecl(int)> x, integral_constant<bool\,0> unnamed002, integral_constant<bool\,0> unnamed003) in c:\luabind\detail\conversion_policies\conversion_base.hpp:line 64 at luabind.detail.make_pointee_instance<class std::function<void cdecl(int)> &,struct std::integral_constant<bool,0> >(lua_State L, function<void __cdecl(int)> x, integral_constant<bool\,0> unnamed002) in c:\luabind\detail\conversion_policies\conversion_base.hpp:line 70 at luabind.detail.ref_converter.to_lua<class std::function<void cdecl(int)> >(ref_converter , lua_State L, function<void cdecl(int)> ref) in c:\luabind\detail\conversion_policies\reference_converter.hpp:line 45 at luabind.detail.push_arguments<struct luabind::meta::type_list<>,1,class std::function<void __cdecl(int)> &>(lua_State L, function<void cdecl(int)> arg0) in c:\luabind\detail\call_function.hpp:line 51 at luabind.detail.call_function_struct<bool,luabind::meta::type_list<>,luabind::meta::index_list<1>,1,&luabind::detail::pcall,0>.call<class std::function<void __cdecl(int)> &>(lua_State L, function<void cdecl(int)> ) in c:\luabind\detail\call_function.hpp:line 121 at luabind.call_pushed_function<bool,struct luabind::meta::type_list<>,class std::function<void __cdecl(int)> &>(lua_State L, function<void cdecl(int)>* ) in c:\luabind\detail\call_function.hpp:line 147 at luabind.call_function<bool,struct luabind::meta::type_list<>,class std::function<void cdecl(int)> &>(object obj, function<void __cdecl(int)> ) in c:\luabind\detail\object.hpp:line 146

decimad commented 7 years ago

Hrmm, it should normally trigger the std::function converter found in function_converter.hpp

decimad commented 7 years ago

Hrmm, I see, it values the reference over the function type and so misses the converter. That's a bug.

decimad commented 7 years ago

Can you try replacing the line 53 in detail/conversion_policies/function_converter.hpp from

   struct default_converter<F, typename std::enable_if<detail::is_function<F>::value>::type>

to

   struct default_converter<F, typename std::enable_if<detail::is_function<typename std::remove_reference<F>::type>::value>::type>

?

decimad commented 7 years ago

That would only be a short term fix though... Ideally all the calls should "semantically" take by value, even if they physically take by ref or rvale ref, with the exception of std::reference_wrapper ... I don't know if I can make that quickly though.

osaengine commented 7 years ago

It's helped but I still some doubt Luabind can work properly with Lua instances. All other methods throws an errors while invoke from C++. From Lua - OK.

osaengine commented 7 years ago

I can send my proj to reproduce but I wanna send it via email (or other non public way).

decimad commented 7 years ago

Well, it would be nice to know the reason for the exceptions, not just that they happen. Did you pass in the object as first argument to the lua methods?

osaengine commented 7 years ago

I call methods like you pointed (get 0x80004005 error):

auto size = call_function(state["Size"]);

In Lua the same (works OK):

local size = state:Size();

osaengine commented 7 years ago

at _CxxThrowException(Void , _s__ThrowInfo ) at luabind.detail.cast_error(lua_State L) in c:\luabind\detail\call_shared.hpp:line 47 at luabind.detail.call_function_struct<int,luabind::meta::type_list<>,luabind::meta::index_list<>,1,&luabind::detail::pcall,0>.call<>(lua_State L) in c:\luabind\detail\call_function.hpp:line 132 at luabind.call_pushed_function<int,struct luabind::meta::type_list<> >(lua_State L) in c:\uabind\detail\call_function.hpp:line 147 at luabind.call_function<int,struct luabind::meta::type_list<> >(object obj) in c:\luabind\detail\object.hpp:line 146

decimad commented 7 years ago

lua methods take the "this" as first argument.

some_object:method(blah) is short for some_object.method(some_object, blah).

Please pass in the object as first argument to the method as in

call_function(state["Size"], state)

osaengine commented 7 years ago

Thanks a lot. Looks all works cool. Will wait you fix with function_converter

decimad commented 7 years ago

Well, and now that I had time to take a look, I found "call_member" inside call_member.hpp, which does exactly the convenience syntax without the proxy object clutter etc..

osaengine commented 7 years ago

Not sure I've got your message. If something need for regression test - I am in.

osaengine commented 7 years ago

Have a small issue with nil values. What the conversion should to use with lua objects? With 0 not work, object always not null:

if (state == 0 || !state.is_valid())
{
// never happen
}