从Lua传递给C++的对象地址,在成员变量中返回了错误的值。
我目前正在尝试使用SWIG工具来生成C ++和Lua代码的包装,进行一些实验。
在与SWIG斗争一番后(尝试设置它,学习它的工作原理等等),我终于获得了一个运行良好的示例。
但是,在我的某个实验中出现了尴尬的结果。
我试图将Lua的userdata恢复为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指针),而不是出现在C ++代码的0xb2d9f0
?
2º - 即使这些指针在不同的地址上,它们似乎都指向相同的Foo对象(或者至少是“一个”Foo对象),除了当我检查C ++ lFoo->getValue()
时,我得到1
而不是4。为什么呢?
我考虑过可能得到了第二个Foo对象,但他的构造函数从未被调用。
3º - 另外,当我将我的Foo的引用传回C ++时,我是否做错了什么?有更好的方法吗?
4º - 最后,当我调用lua_close(lLuaState);
时,Foo的析构函数被调用。有没有办法让我在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
附注:对于长篇的帖子我感到抱歉。如果有改进的方法,我将非常乐意倾听。
原文链接 https://stackoverflow.com/questions/5523979
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
因为在 C++ 侧输出的指针值
lFoo
与构造的Foo
对象均不同,因此我们可以得出结论:lFoo
指向的不是Foo
对象。lFoo->getValue()
返回的并不是存储在Foo
对象中的4
,因为lFoo
上的数据不是Foo
,而是封装。以下是一种方法:在
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);
Foo
值,可以传递0
而非SWIG_POINTER_DISOWN
。