【问题标题】:How to use shared_ptr in LuaJIT FFI/C++ binding?如何在 LuaJIT FFI/C++ 绑定中使用 shared_ptr?
【发布时间】:2016-08-11 07:17:00
【问题描述】:

我正在创建一个与另一个 C++ 项目的 Lua 绑定。经过一番调查,LuaJIT FFI 似乎是实现这一目标的最佳选择。我真的受益于 lua 用户邮件列表存档 [1] 和另一张相关幻灯片 [2]。实际上,这里已经完成了一个 Hello World 示例 [3],欢迎提出任何改进建议。

目前我正在尝试将shared_ptr 引入此示例,这样我就不需要关心垃圾收集问题。但由于我在 Lua 和 LuaJIT 上的经验不佳,Lua 脚本总是返回 Segmentation fault,我什至不知道如何调试它。下面列出sn-ps的代码,希望各位有识之士能给我一些实用的建议。

这是hello.cpp,我用来创建库的命令是g++ -std=c++11 -shared -fPIC -o libhello.so hello.cpp

#include<memory>
using namespace std;

class Hello {
    public:
        const char* World()
        {
             return "Hello World!\n";
         }
};

typedef shared_ptr<Hello> pHello;

extern "C" {
    pHello Hello_new(){
        return pHello();
    }

    const char* Hello_World(pHello self){
        return self->World();
    }
}

这是hello.lua,运行命令为luajit hello.lua

ffi = require('ffi')
ffi.cdef[[
    typedef struct pHello pHello;

    pHello Hello_new();
    const char* Hello_World(pHello);
]]
hello = ffi.load('hello')

hello_index = {
    World = hello.Hello_World
}
hello_mt = ffi.metatype('pHello', {
    __index = hello_index
})
Hello = hello.Hello_new

hello = Hello()
io.write(ffi.string(hello:World()))

【问题讨论】:

  • 我不知道 LuaJIT 是怎么接受你的 cdef 的; struct pHello 没有定义,所以 LuaJIT 不可能知道它有多大以及 Hello_new 返回多少字节。在任何情况下,都不要在 C API 中直接公开 shared_ptr - 没有好办法让它在 C 中工作。

标签: c++ c++11 binding lua luajit


【解决方案1】:

事情并不像你期望的那样工作。

首先,您的 C++ 代码存在缺陷:调用 return pHello() 返回一个没有托管对象的空 shared_ptr(例如:空指针)。如果要创建新对象,请致电return std::make_shared&lt; Hello &gt;()

除此之外,使用shared_ptr 对垃圾收集没有帮助。智能指针完成的引用计数依赖于被调用的析构函数,这是一种 C++ 机制。由于 FFI 库与 C 代码接口,无论您如何包装它以将其传递给 LuaJIT,这都不会发生(您的编译器应该警告您有关使用 `extern "C" 和类类型返回类型) .

标准方法(如果你想依赖垃圾回收)是让__gc 元方法调用一个在 C++ 端执行delete 的函数。这是 C 的方式:你在函数调用中分配了一个资源,然后你负责释放它。

我建议为您的类编写一个简单的包装器,也许首先使用纯 Lua API 来学习基础知识。稍后,当您有共享对象并且不想自己进行引用计数时,请继续包装 shared_ptr

【讨论】:

  • 感谢您的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 2011-08-20
  • 2011-08-07
  • 2019-09-21
  • 2012-09-01
  • 2011-07-28
相关资源
最近更新 更多