Sign in to follow this  

Luabind: Passing C++ objects

This topic is 3196 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I do remember, when I was playing with luabind 0.7, that in order to pass a C++ object(or pointer to object) to a lua function, one just needed to expose the class to luabind and pass a object as an argument to call_function. Now I'm using luabind 0.8 with lua 5.1, and... ... what I'm doing wrong?
#include <iostream>
#include<luabind/luabind.hpp>
extern "C"
  {
#include <lualib.h>
#include <lua.h>
#include <lauxlib.h>
  }

using namespace std;
using namespace luabind;
int DebuggerFunc(lua_State* L)
{

object error_msg(luabind::from_stack(L, -1));
cerr << error_msg << endl;
  return 0;
}

class teste
{
public:
 void Print(){cout<<"aaaa"<<endl;}

};


int main()
{

    try
    {
        teste *obj=new teste;

		lua_State *myLuaState = lua_open();
		luaL_openlibs(myLuaState);
        luabind::open(myLuaState);

         module(myLuaState)
            [
            class_<teste >("teste")
        .def(constructor<>())
        .def("Print", &teste::Print)
            ];

        luaL_dofile(myLuaState,"script.lua");
        luabind::call_function<void>(myLuaState,"DoStuff", obj);

        lua_close(myLuaState);

    }
    catch (const luabind::error &er)
	{
		cerr << er.what() << endl;
		lua_State* Ler=er.state();
		DebuggerFunc(Ler);
	}
	catch (...)
	{
	    cerr<<"Uknow error!"<<endl;
	}

	return 0;
}


the script is as follows: function DoStuff(obj) obj:Print() end The Error message: "lua runtime error script.lua:4: attempt to index local 'obj' (a userdata value)" If it is not the way to do it, what is then? And I've also tried with a non pointer object, same stuff. thank's

Share this post


Link to post
Share on other sites
Your code works fine for me. Are you sure this is the exact test case that's failing for you? Which compiler are you using, and how do you build and link to luabind?

Share this post


Link to post
Share on other sites
Yes, I'm sure, I've just copy/pasted it.

I'm Using luabind 0.8 and lua 5.1.4, my compiler is the one that comes with visual c++ 2008 express edition(using it with code::blocks).

I've download and compiled boost 1.37 with bjam, and download lua from the original website(precompiled bins for windows). Put boost in BOOST_ROOT (and BOOST_BUILD_PATH as well), and lua in LUA_PATH system variables. then, I've run bjam in luabind directory and it compiled. Everything else works but this.

There is a 8.1 version of luabind, I shall try this and see what happens.

EDIT: Luabind 0.81 = Same thing

Share this post


Link to post
Share on other sites
I verified that it works correctly for me with VC9.0Express. Can you run the test suite? "bjam toolset=msvc-9.0express test" in the luabind directory.

Share this post


Link to post
Share on other sites
Yes, I was able to do it, an it took considerably longer to finish. It has compiled a static version and a Dynamic version, debug and release.

Can you tell me what I have done? And what should I do now?

Share this post


Link to post
Share on other sites
Ok, now it works, I think code::blocks got confused, I used the same librarys I did before, but know in a new project, and it worked.

But, this test is just a simplification of a larger project I'm on, and I Get a very similar situation.


//binding, s is my lua_State variable

module(s)
[
class_<CClientBase>("CClientBase")
.def(constructor<>())

];
module(s)
[
class_<CMessengerClient,CClientBase>("CMessengerClient")
.def(constructor<>())
.def("GetId", &CMessengerClient::GetId)
];

...

//function on accept CPP


template <class CClient,class CBuffer> void CMessengerServer<CClient,CBuffer>::OnAccept(CClient* client, CBuffer* buffer,int bytes,int tn)
{
//call a lua function to deal with it
try
{
cout<<client->GetId()<<endl;
luabind::call_function<void>(lua_states[tn-1],"OnAccept",client,buffer,bytes,tn);
}
catch (const luabind::error &er)
{
cerr << er.what() << endl;
lua_State* Ler=er.state();
DebuggerFunc(Ler);
}
catch (...)
{
cerr<<"Uknow error!"<<endl;
}
}




The OnAccept C++ function just Pass on to a OnAccept lua Function

script:

function OnAccept(client,buffer,bytes,tn)
print "stuff"
print(client:GetId())

end

I know my bindings for the rest(cause there is a lot more) of my code is working, because it works till it is time to accept a connection.

For my surprise, the cout<<client->GetId()<<endl; works and print the right thing on the screen, proving it is a valid pointer, but, when its time to lua to call GetId, the program just Crashes, yeah, Crashes, no Exception catch.

the output is something like
1
stuff
CRASH!!!

Share this post


Link to post
Share on other sites
OK, now I've change to GCC (Mingw), and I'm able to Grab a Assert saying I'm trying to use an unregistered type.

My binder function (Complete):



lua_State* LuabindOpen ()
{
lua_State* s=lua_open();;
luaL_openlibs(s);
luabind::open(s);

module(s)
[
class_<CBufferBase>("CBufferBase")
.def(constructor<int>())


];

module(s)
[
class_<CMessengerBuffer,CBufferBase>("CMessengerBuffer")
.def(constructor<int>())
.def("GetBytesToSend", &CMessengerBuffer::GetBytesToSend)
];

module(s)
[
class_<CClientBase>("CClientBase")
.def(constructor<>())
];

module(s)
[
class_<CMessengerClient,CClientBase>("CMessengerClient")
.def(constructor<>())
.def("GetId", &CMessengerClient::GetId)
];

module(s)
[
class_<CServer<CMessengerClient,CMessengerBuffer> >("CServer")
.def(constructor<>())
];

module(s)
[
class_<CMessengerServer<CMessengerClient,CMessengerBuffer>, CServer<CMessengerClient,CMessengerBuffer> >("CMessengerServer")
.def(constructor<>())
.def("Start",(bool(CMessengerServer<CMessengerClient,CMessengerBuffer>::*)(int))&CMessengerServer<CMessengerClient,CMessengerBuffer>::Start)
.def("Finish", &CMessengerServer<CMessengerClient,CMessengerBuffer>::Finish)
.def("SetName", &CMessengerServer<CMessengerClient,CMessengerBuffer>::SetName)
.def("GetName", &CMessengerServer<CMessengerClient,CMessengerBuffer>::GetName)
.def("GetNumberOfProcessors", &CMessengerServer<CMessengerClient,CMessengerBuffer>::GetNumberOfProcessors)
.def("GetIp", &CMessengerServer<CMessengerClient,CMessengerBuffer>::GetIp)
.def("PostSend", &CMessengerServer<CMessengerClient,CMessengerBuffer>::PostSend)
.def("OpenLuaStates", &CMessengerServer<CMessengerClient,CMessengerBuffer>::OpenLuaStates)
.def("OpenLuaScript", &CMessengerServer<CMessengerClient,CMessengerBuffer>::OpenLuaScript)
.def("GetNextId", &CMessengerServer<CMessengerClient,CMessengerBuffer>::GetNextId)
.def("AddClient", &CMessengerServer<CMessengerClient,CMessengerBuffer>::AddClient)
.def("SendToAll", &CMessengerServer<CMessengerClient,CMessengerBuffer>::SendToAll)
.def("SendToAllBut", &CMessengerServer<CMessengerClient,CMessengerBuffer>::SendToAllBut)
.def("SendTo", &CMessengerServer<CMessengerClient,CMessengerBuffer>::SendTo)
.def("Remove", &CMessengerServer<CMessengerClient,CMessengerBuffer>::Remove)
.def("ToClientType", &CMessengerServer<CMessengerClient,CMessengerBuffer>::ToClientType)
.def("ToBufferType", &CMessengerServer<CMessengerClient,CMessengerBuffer>::ToBufferType)
];

module(s)
[
def("GetServer", &GetServer),
def("ToInt",&ToInt)
];

return s;
}




As you can see, I'm binding it as any of my other classes.

When I try to do this:

function OnAccept(client,buffer,bytes,tn)
teste=CMessengerClient()
print(teste:GetId())
end
Crashes: "Trying to use an unregistered type"

But when I do this:

function OnAccept(client,buffer,bytes,tn)
teste=CMessengerBuffer(1024)
print(teste:GetBytesToSend())
end

Works!

I really don't understand. Both classes are been bound exactly the same way.

Please, I need some help here. I'm completely lost.

Share this post


Link to post
Share on other sites
I've found my problem. GetId was returning a unsigned long long. Aparently I can't do that. I Really want it to be unsigned long long, and I can fit my design in order to not need to call the unsigned long long functions inside lua. Or I could make those unsigned long long on simple unsigned integers (long long was just to be shure [lol]).

But,is there a way to use unsigned long long integer with lua?


Thank you for you help.

Share this post


Link to post
Share on other sites
isn't unsigned long long a 64 bit unsigned value? Hmm perhaps wrapping it in a struct called something say big_num_64 and just binding that with Luabind? Alittle trouble but then u can return big_num_64 from Lua without any problems.

Good Luck!

-ddn

Share this post


Link to post
Share on other sites
Quote:
Original post by ddn3
isn't unsigned long long a 64 bit unsigned value? Hmm perhaps wrapping it in a struct called something say big_num_64 and just binding that with Luabind? Alittle trouble but then u can return big_num_64 from Lua without any problems.

Good Luck!

-ddn


Sure, i think I could do that. But I still will be unable to get those values from inside lua, like print it on the the screen with print, or do some calculation. Maybe this solve part of the problem, if there is no other solution, I think I could live with it.

And yes, it is a 64 bits unsigned value (A very big number).

Share this post


Link to post
Share on other sites
You can provide meta methods for the object to allow you to print, add, sub, div etc it like a number (but only against its own type I think).

see:

http://www.lua.org/pil/13.html

-ddn

Share this post


Link to post
Share on other sites
Quote:
Original post by Escarab
I've found my problem. GetId was returning a unsigned long long. Aparently I can't do that. I Really want it to be unsigned long long, and I can fit my design in order to not need to call the unsigned long long functions inside lua. Or I could make those unsigned long long on simple unsigned integers (long long was just to be shure [lol]).

But,is there a way to use unsigned long long integer with lua?


Lua stores all numbers as double. Unless your integers are too big to be stored as double, you can specialize luabind::default_converter<> for unsigned long long. Something like this should work:

namespace luabind {

template <>
struct default_converter<unsigned long long>
: native_converter_base<unsigned long long>
{
static int compute_score(lua_State* L, int index)
{
return lua_type(L, index) == LUA_TNUMBER ? 0 : -1;
}

unsigned long long from(lua_State* L, int index)
{
return static_cast<unsigned long long>(lua_tonumber(L, index));
}

void to(lua_State* L, unsigned long long value)
{
lua_pushnumber(L, static_cast<lua_Number>(value));
}
};

template <>
struct default_converter<unsigned long long const>
: default_converter<unsigned long long>
{};

template <>
struct default_converter<unsigned long long const&>
: default_converter<unsigned long long>
{};

} // namespace luabind

Share this post


Link to post
Share on other sites

This topic is 3196 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this