- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我需要在我的主程序中提供数据结构指针,其中我定义了 Lua 状态,指向通过使用 SWIG 包装 C++ 代码创建的动态加载的 Lua 模块。
这是我的代码示例:
在 SimpleStruct.h 中:
#pragma once
struct SimpleStruct
{
int a;
double b;
};
在 exmaple.h(这个是用 SWIG 编译的)到 Lua 库:
#pragma once
#include "SimpleStruct.h"
#include <iostream>
class TestClass
{
public:
TestClass()
{
std::cout<<"TestClass created"<<std::endl;
}
~TestClass() {}
void ReadSimpleStruct(void * tmp)
{
std::cout<<"reading pointer: "<<std::endl;
SimpleStruct * pp = reinterpret_cast< SimpleStruct * >(tmp);
std::cout<<"Simple Struct: " << pp->a << " " << pp->b << std::endl;
}
};
仅在 example.cpp 中:
#include "example.h"
这是我的主程序(LuaTest.cpp):
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <iostream>
#include "SimpleStruct.h"
int main(int argc, char ** argv)
{
lua_State * L = luaL_newstate();
luaL_openlibs(L);
SimpleStruct * ss = new SimpleStruct();
ss->a = 1;
ss->b = 2;
lua_pushlightuserdata(L,ss);
lua_setglobal( L, "myptr");
int s = luaL_dostring(L, "require('example')");
s = luaL_dostring(L, "mc = example.TestClass()");
s = luaL_dostring(L, "mc:ReadSimpleStruct(myptr)");
if(s)
{
printf("Error: %s \n", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
std::cout<<"done"<<std::endl;
return 0;
}
example.i(从 SWIG 中的 Lua 示例复制而来):
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"
然后我按如下方式编译所有内容:
swig -c++ -lua example.i
g++ -c -fpic example.cpp example_wrap.cxx -I/usr/local/include -I/usr/include/lua5.2/
g++ -shared example.o example_wrap.o -o example.so
g++ LuaTest.cpp -o luatest -llua5.2 -I/usr/include/lua5.2/ -Wall
在 Ubuntu 16.04 上(以及在 osx 上,路径不同但结果相同)。
在 Lua 脚本的最后一行我遇到了段错误(当我尝试访问“mc:ReadSimpleStruct(myptr)”中的 pp->a 时)。
所以我的问题是:如何使用 Lua 轻型用户数据向加载的 Lua 库提供指向 C++ 对象的指针?
总的来说:我的主程序中有一个带有游戏参数和对象的类,我想提供一个指向该类的指针,指向其他使用 SWIG 编译的已加载 Lua 库。
最佳答案
通过使用调试器(或者只是在 TestClass::ReadSimpleStruct
中打印一些额外内容),我们至少可以很快看到段错误的表面原因。在我的测试设置中,函数的 tmp
参数的值为 0x20
。这显然是不对的,但了解为什么以及如何解决它需要更多的调查。
作为起点,我又添加了一个对 luaL_dostring(L, "print(myptr)")
的调用,并使用调试器检查全局变量是否按预期正常工作。为了更好地衡量,我在每次调用 luaL_dostring
之后添加了一些断言语句,因为您实际上只是在检查最后一个的返回值,尽管在这里并没有真正产生任何区别。
我这辈子写的 Lua 不多,所以我查看了 'Light userdata' 的文档。 ,我看到你正在使用但不知道它是什么。这听起来很理想:
A light userdatum is a value that represents a C pointer (that is, a void * value)
问题是,如果我们检查生成的 example_wrap.cxx 文件,我们可以看到 SWIG 实际上试图比这更聪明,如果我们在生成之前跟踪 arg2
的代码调用 (arg1)->ReadSimpleStruct(arg2)
我们可以看到它正在调用 SWIG_ConvertPtr
(最终调用 SWIG_Lua_ConvertPtr
),然后执行以下操作:
lua_touserdata(L, index);
//... Some typing stuff from the macro
*ptr=usr->ptr; // BOOM!
即您正在做的不是 SWIG 希望看到的 void *
,SWIG 希望通过其类型系统将它们全部管理为来自其他函数或 SWIG 管理的全局变量的返回值。 (我有点惊讶 SWIG 让这个达到段错误而没有引发错误,但我认为这是因为 void*
在某种程度上是特殊情况)
这个老问题很好地证明了我对 lua_pushlightuserdata
的理解。 .基本上,我们将需要编写自己的类型映射,以按照您尝试使用它的方式处理此函数参数(如果您真的不想让 SWIG 管理它?)。我们要做的很简单。这里的用例也与我链接的示例基本相似,除了我们调用 lua_touserdata
时所追求的变量是一个函数参数。这意味着它在堆栈中处于正偏移量,而不是负偏移量。 SWIG 实际上可以通过 $input
替换告诉我们类型映射中的偏移量,因此我们的类型映射不仅适用于成员函数的第一个参数。
所以我们的类型映射,它对我们修改后的 example.i 文件中的任何函数参数 void * tmp
执行此操作变为:
%module example
%{
#include "example.h"
%}
%typemap(in) void * tmp %{
$1 = lua_touserdata(L, $input);
%}
%include "example.h"
然后编译并运行:
swig -c++ -lua example.i
g++ -fPIC example_wrap.cxx -I/usr/local/include -I/usr/include/lua5.2/ -shared -o example.so && g++ -Wall -Wextra LuaTest.cpp -o luatest -llua5.2 -I/usr/include/lua5.2/
./luatest
TestClass created
userdata: 0x11d0730
reading pointer: 0x11d0730
Simple Struct: 1 2
done
关于c++ - 在用 SWIG 编译的 c 和 lua 模块之间共享数据指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40683578/
如何从 a.lua 传递值至 b.lua ? 让我们说在我的 a.lua我有这个变量代码。 local value = "Hello WOrld!" director:changeScene ("b"
我有一个使用命令行解释器运行的 lua 脚本,该脚本需要从文件加载表。 该表存储如下: create_object_action = { reflexive = true, which
我通过静态链接的方式在我的项目中嵌入了 Win32 上的 Lua(不,我不能切换到 DLL)。我想捆绑更多使用 native 代码的 Lua 扩展 - 而不仅仅是纯 .lua 文件。具体来说,我想捆绑
我需要一些帮助来解析 lua 文件的命令行。我正在执行一个 lua 文件,该 lua 文件有一个命令“dofile(2nd.lua-file)”,但是,我想通过第一个 lua 文件将一些参数传递给第二
这是我的代码示例: listOfPeople = {} listOfPeople["test"] = "hello" listOfPeople = nil “hello”字符串是否丢失并形成内存泄漏?
在一些源代码中,我看到了“Underscore.lua”模块的用法。 _ = require 'underscore' 描述如下: Underscore.lua is a Lua library th
在一些源代码中,我看到了“Underscore.lua”模块的用法。 _ = require 'underscore' 描述如下: Underscore.lua is a Lua library th
我一直在编程 io.write("How many languages do you speak?\n") answer = io.read() if (answer == 1) then io.wr
这个问题在这里已经有了答案: Getting multiple values from a function without creating a variables in LUA (2 个答案)
在阅读 Lua manual 时我遇到了这部分: 函数调用和赋值都可以以左括号开头。这种可能性导致了 Lua 语法中的歧义。考虑以下片段: a = b + c (print or io.write)(
假设我有以下循环: for name in poll() do if name == "quit" then return 0 end end "quit" 字符串是否
Pandoc 通过其 --lua-filter 参数原生支持 lua 过滤器。 但是,我想知道它使用的是什么版本的 lua,以及是否可以将 lua 模块(我相信它依赖于 C 代码)导入其中。 这是我调
这种语言是面向对象的语言吗? 它经常用作OO语言吗? 最佳答案 Lua 完全有能力 prototype-based类似于 JavaScript 的面向对象编程。 Prototype-based pro
我想从 C++ 传递一个 Lua 脚本(Lua 解释器可以处理的代码)并取回结果。 我在网上查看,但找不到任何可以帮助我的示例。我可以从 C++ 调用 Lua 函数,但这需要您使用 Lua 函数创建一
我正在阅读“在 Lua 中编程”,但我不明白这段代码中 Lua 中函数的行为: function newCounter () local i = 0 return function () --
我最近一直在查找 Lua 中的链表,并有一个简单的问题,到目前为止我还没有找到答案 local head = nil head = {next = head, value = "d"} head =
我知道有tonumber()函数,但是问题是我需要转换较大的数字,例如1000100110100011111010101001001001001100100101。我可以自己写,但是有没有办法将其集成
是否可以在 Lua 中对多个值执行算术运算。 我在 Windows 5.1.4 上使用 Lua。 目前我必须将多个值放入一个表中,然后解压缩它们,我希望能够跳过这一步。 是否可以。 这是我目前拥有的:
有什么区别吗 local splitPathFileExtension = function (res) end 和 function splitPathFileExtension(res) end
在下面的代码中,谁能解释一下 b,a = a,b 内部是如何工作的? -- Variable definition: local a, b -- Initialization a = 10 b = 3
我是一名优秀的程序员,十分优秀!