I'm currently trying some experiences with the SWIG tool for wrapping generation of C++ and Lua code.
After some fighting with SWIG (trying to set it up, learn how it works, etc...), I finally got a working example.
However, I've come up with an awkward result in one of my experiments.
I was trying to recover a Lua's userdata back to C++ and change some of it's values.
Here is what i got in my console results:
Console
C++: index.cpp
Lua: Foo.lua
C++: Constructor of 0xb2d9f0
Lua: Adress of lFoo = userdata: 0xb35048
C++: Set - Old = 12 New = 4
Lua: Foo->Value = 4
Lua: Bye World
C++: Lua's lFoo To C++
C++: Adress of lFoo = 0xb35048
C++: Foo->Value = 1
C++: Set - Old = 1 New = 44
C++: Popping Foo from Lua
C++: Closing lLuaState
C++: Destructor of 0xb2d9f0
C++: Bye World
Before I state where things are getting confused to me, let me paste some of the other codes is this examples, so that the console output gets lesser abstract:
Foo.h
#ifndef FOO_H_
#define FOO_H_
#include <iostream>
class Foo
{
public:
Foo( int a_value );
virtual ~Foo();
int getValue(){ return m_value; }
void setValue( int a_value )
{
std::cout << "C++: Set - Old = " << m_value << " New = " << a_value << "\n";
m_value = a_value;
}
private:
int m_value;
};
#endif /* FOO_H_ */
Foo.cpp
#include "Foo.h"
Foo::Foo( int a_value ) : m_value( a_value )
{
std::cout << "C++: Constructor of " << this << "\n";
//setValue( a_value );
}
Foo::~Foo()
{
std::cout << "C++: Destructor of " << this << "\n";
}
index.cpp
#include <string>
#include <iostream>
#include <lua.hpp>
#include "Foo.h"
extern "C" int luaopen_Foo(lua_State* L); // declare the wrapped module
const std::string ctLuaFooFile = "Foo.lua";
int main( int argc, char * args[] )
{
std::string lLuaFile = ctLuaFooFile;
std::cout << "C++: index.cpp\n";
lua_State *lLuaState;
lLuaState = lua_open();
luaL_openlibs( lLuaState );
luaopen_Foo( lLuaState );
Foo * lFoo;
if ( luaL_loadfile( lLuaState, lLuaFile.c_str() ) == 0 ) // load and run the file
{
int lError = lua_pcall( lLuaState, 0, 0, 0 );
if ( lError )
{
std::cout << "Lua Error: " << lua_tostring( lLuaState, -1 );
lua_pop( lLuaState, 1 ); /* pop error message from the stack */
}
std::cout << "C++: Lua's lFoo To C++\n";
lua_getglobal( lLuaState, "lFoo");
lFoo = static_cast<Foo *>( lua_touserdata( lLuaState, -1 ) );
std::cout << "C++: Adress of lFoo = " << lFoo << "\n";
std::cout << "C++: Foo->Value = " << lFoo->getValue() << "\n";
lFoo->setValue( 44 );
std::cout << "C++: Popping Foo from Lua\n";
//Is Foo's destructor invoked here? --No
lua_pop( lLuaState, -1 );
}
else
{
std::cout << "unable to load" << lLuaFile << "\n";
}
std::cout << "C++: Closing lLuaState \n";
//Foo's destructor getting invoked here!
lua_close( lLuaState );
std::cout << "C++: Bye World\n";
if( lFoo )
{
delete lFoo;
}
return 0;
}
Now that things are a little clearer on how I got those console outputs, let me tell you where my questions lie:
1º - Why, when I got the reference from lFoo
back to C++, in line lFoo = static_cast<Foo *>( lua_touserdata( lLuaState, -1 ) );
its address was 0xb35048
(which seems to be a specific Lua pointer) instead of 0xb2d9f0
(which appeared in the C++ side of the code)?
2º - Even if those pointers are on different addresses, they both appear to be pointing to the same Foo object (or at least, to "a" Foo object), except that when I check C++ lFoo->getValue()
I get 1
instead of 4. Why is that?
I consided that i could be getting an second Foo object, but his constructor was never called.
3º - Also, am I doing something wrong when I get my Foo's reference back to C++? Is there a better way of doing it?
4º - And finally, when I call lua_close( lLuaState );
, Foo's Destructor is getting called. Is there a way for me to change the responsability of destroying this object in the C++ side? I think i read something about it in the SWIG docs but I can't seen to remember where.
For those willing to try my experiment, I will leave here the Foo.i
interface file, used by the SWIG tool to create Foo_wrap.cxx, as well as the console commands used by my Eclipse, SWIG and g++ compiler:
Foo.i
/* File : example.i */
%module Foo
%{
#include "Foo.h"
%}
/* Let's just grab the original header file here */
%include "Foo.h"
Console commands
**** Build of configuration Debug for project SwigDemo ****
make pre-build main-build
Criando wrappers para lua
swig -c++ -lua ../Foo.i
Building file: ../Foo.cpp
Invoking: GCC C++ Compiler
g++ -I/usr/include/lua5.1 -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"Foo.d" -MT"Foo.d" -o"Foo.o" "../Foo.cpp"
Finished building: ../Foo.cpp
Building file: ../Foo_wrap.cxx
Invoking: GCC C++ Compiler
g++ -I/usr/include/lua5.1 -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"Foo_wrap.d" -MT"Foo_wrap.d" -o"Foo_wrap.o" "../Foo_wrap.cxx"
Finished building: ../Foo_wrap.cxx
Building file: ../index.cpp
Invoking: GCC C++ Compiler
g++ -I/usr/include/lua5.1 -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"index.d" -MT"index.d" -o"index.o" "../index.cpp"
Finished building: ../index.cpp
Building target: SwigDemo
Invoking: GCC C++ Linker
g++ -L/usr/lib -L"/home/bruno/Programas/eclipse/workspace/SwigDemo/Debug" -o"SwigDemo" ./Foo.o ./Foo_wrap.o ./index.o -llua5.1
Finished building target: SwigDemo
Ps: I'm sorry for the long post. If there is a ways to improve it, I'd be more than happy to listen about it.