Luabind: Passing C++ objects

Started by
13 comments, last by dw9 15 years, 1 month ago
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
Advertisement
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?
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
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.
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?
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 variablemodule(s)	[	    class_<CClientBase>("CClientBase")	    .def(constructor<>())	 	];	module(s)	[	    class_<CMessengerClient,CClientBase>("CMessengerClient")	    .def(constructor<>())	    .def("GetId", &CMessengerClient::GetId)	];...//function on accept CPPtemplate <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!!!
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.
Can you reduce this to a minimal (and complete) test case? AFAICT, the code looks correct and should work.
Sure, I Will do It. But I'm feeling it will work in the test, but i will try hard for it not work. I will do it as soon as I Get home.
There are some unit test which come with Luabind. Have you tried running them and do they all pass?

-ddn

This topic is closed to new replies.

Advertisement