Адрес объекта, переданный из Lua в C ++, возвращает мне неправильное значение в переменной-члене - PullRequest
1 голос
/ 02 апреля 2011

В настоящее время я пытаюсь получить опыт работы с инструментом 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: простите за длинный пост.Если есть способы улучшить его, я буду более чем счастлив выслушать его.

1 Ответ

1 голос
/ 03 апреля 2011

1) Поскольку значение указателя lFoo, которое вы выводите на стороне C ++, отличается от любого созданного Foo, мы можем заключить, что lFoo не указывает на объект Foo.

2) lFoo->getValue() не возвращает 4, который был сохранен в объекте Foo, потому что данные в lFoo не Foo, а оболочка.

3) Вот один из способов: в index.cpp прочитать содержимое модуля Foo (и больше не ссылаться на него):

#include "foo_wrap.cxx"

Заменить

lFoo = static_cast<Foo*>(lua_touserdata(lLuaState, -1));

с

void* ptr;
SWIG_ConvertPtr(
    lLuaState, -1, &ptr, SWIGTYPE_p_Foo, SWIG_POINTER_DISOWN);
lFoo = static_cast<Foo*>(ptr);

4) Передайте 0 вместо SWIG_POINTER_DISOWN, если вы не хотите вступать во владение значением Foo.

...