gpt4 book ai didi

c - Lua C API 推送现有指针

转载 作者:太空宇宙 更新时间:2023-11-03 23:31:12 24 4
gpt4 key购买 nike

假设我有一个 C 端拥有的指针,我希望以用户数据的形式将其插入 Lua 堆栈。在不牺牲指定特定元表的能力的情况下,实现此目标的最佳方法是什么?

我最初的想法是使用轻型用户数据,但从我读到的内容来看 here ,所有轻型用户数据共享一个公共(public)元表。这是不可取的,因为它会强制我所有的 c 面对象的共同行为。

考虑到我希望为 Lua 分配的对象重用元表,只需将一个不同的 this 指针传递给元方法,我的第二个想法涉及将一个人工的 this 指针附加到用户数据对象。

struct ud
{
struct T* ptr;
struct T data;
};

struct ud* p = (struct ud*)lua_newuserdata(L, sizeof(struct ud));
p->ptr = &(p->data);

或者,在推送轻量级用户数据的情况下

struct T object;
struct T** p = (struct T**)lua_newuserdata(L, sizeof(struct T*));
*p = &object;

是推荐附加一个 this 指针,还是有更 API 友好的替代方法?我的最终目标只是将现有的指针推送到 Lua,并将元表与其相关联,这样元表就可以为重度和轻度用户数据重用。

最佳答案

一种常见的(但不是唯一的)方法是使用一种称为“盒装指针”的技术。这个想法是你分配一个足够大的用户数据来保存指针,然后将你的元表等附加到它。

void push_pointer(lua_State *L, void *p) {
void **bp = lua_newuserdata(L, sizeof(p));
*bp = p;

// setup metatable, etc
}

然后通过元表调用的函数将在堆栈上接收此用户数据,然后您从中解压缩原始指针。

// called via metatable
int some_function(lua_State *L) {
assert(lua_type(L, 1) == LUA_TUSERDATA);
void **bp = lua_touserdata(L, 1);
void *p = *bp;

// do stuff with p
}

在执行此操作时,您必须考虑几件事情:

  • 对象生命周期。如果 C 端对象被释放,而 Lua 端的某些东西引用了它的用户日期,那么你就会有一个悬空指针。如果这是可能发生的事情,那么您需要一种方法来处理它。我自己处理了这个问题,方法是拥有一个“实时”C 对象的注册表,我可以在尝试使用指针之前对其进行检查。

  • 用户数据相等。因为你为每个指针推送一个新的用户数据,所以两个具有相同指针的用户数据在 Lua 中不会比较相等。如果这对您很重要,您可以通过几种方式来处理它。 __eq 元方法是最简单的,但并不总是合适的。我使用上面提到的相同对象注册表来提供指针-> 用户数据映射,然后在推送时,如果我已经有指针的用户数据,我就推送它而不是创建一个新的。

    <

关于c - Lua C API 推送现有指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15038796/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com