В настоящее время я пытаюсь получить опыт работы с инструментом SWIG для создания генерации кода на C ++ и Lua.
После некоторой борьбы с SWIG (попытка настроить его, узнать, как он работает, и т. Д ...), Я наконец получил рабочий пример.
Однако в одном из моих экспериментов я получил неловкий результат.
Я пытался восстановить пользовательские данные Lua обратно в C ++ иизмените некоторые из его значений.
Вот что я получил в своей консоли:
Консоль
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
Прежде чем я скажу, где что находитсясмущаясь, позвольте мне вставить некоторые другие коды в этом примере, так что вывод на консоль становится менее абстрактным:
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;
}
Теперь, когда мне стало немного понятнееэти выводы консоли, позвольте мне рассказать вам, где лежат мои вопросы:
1º - Почему, когда я получил ссылку от lFoo
назаддля C ++ в строке lFoo = static_cast<Foo *>( lua_touserdata( lLuaState, -1 ) );
его адрес был 0xb35048
(который, кажется, является специфическим указателем Lua) вместо 0xb2d9f0
(который появился в стороне кода C ++)?
2º - Четныйесли эти указатели находятся по разным адресам, они оба указывают на один и тот же объект Foo (или, по крайней мере, на «a» объект Foo), за исключением того, что когда я проверяю C ++ lFoo->getValue()
, я получаю 1
вместо 4.Почему это так?
Я подумал, что мог бы получить второй объект Foo, но его конструктор никогда не вызывался.
3º - Кроме того, я делаю что-то не так, когда получаю ссылку на Fooвернуться к C ++?Есть ли лучший способ сделать это?
4º - И наконец, когда я звоню lua_close( lLuaState );
, вызывается деструктор Фу.Есть ли способ для меня изменить ответственность уничтожения этого объекта на стороне C ++?Я думаю, что я читал что-то об этом в документации SWIG, но я не могу вспомнить, где.
Для тех, кто хочет попробовать мой эксперимент, я оставлю здесь файл интерфейса Foo.i
, используемыйс помощью инструмента SWIG для создания Foo_wrap.cxx, а также консольных команд, используемых моим компилятором Eclipse, SWIG и g ++:
Foo.i
/* File : example.i */
%module Foo
%{
#include "Foo.h"
%}
/* Let's just grab the original header file here */
%include "Foo.h"
Консольные команды
**** 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: простите за длинный пост.Если есть способы улучшить его, я буду более чем счастлив выслушать его.