gpt4 book ai didi

c - 如何在 C 中的 Lua 模块内创建 Lua 模块?

转载 作者:行者123 更新时间:2023-12-03 14:14:18 25 4
gpt4 key购买 nike

我有一个Actor,我想给它一个Script

我不想拥有多个共享对象,而是想要一个包含其自身依赖项的单个顶级模块。

换句话说,我希望能够做到这一点:

Actor  = require 'Actor'
Script = require 'Actor.Script'

script = Script("To be, or not to be ...");
actor = Actor();

这两个都简单地返回创建 ActorActor.Script 类型的 userdata 的函数。我的问题是,虽然我可以加载此代码,但它无法按预期工作。看起来 Script 只是简单地以某种方式返回了一个 Actor userdata

print(script) => Actor 0x7fb7a240e998
print(actor) => Actor 0x7fb7a240a478

我期待:

print(script) => Actor.Script 0x7fb7a240e998
print(actor) => Actor 0x7fb7a240a478

如果我将代码“分解”到两个不同的模块中,我会得到预期的结果,但我真的很想将它放在一个模块中。

我在 OSX 和 Clang 上编译:

clang -Wall -I./ -I/usr/local/include/ -bundle -undefined dynamic_lookup actor.c script.c -o Actor.so -L./ -L/usr/local/lib

这是我使用的代码:

actor.c:

#include "common.h"

#define ACTOR_LIB "Actor"

typedef struct Actor {
struct Script *script;
} Actor;

/*
* Allocate, initialize, and push a new Actor onto the stack.
* Returns a pointer to that Actor.
*/
Actor*
lua_newactor (lua_State *L)
{
Actor *actor = lua_malloc(L, sizeof(Actor));
actor->script = NULL;
return actor;
}

/*
* Make sure the argument at index N is a actor and return it if it is.
*/
Actor*
lua_checkactor (lua_State *L, int index)
{
return (Actor *) luaL_checkudata(L, index, ACTOR_LIB);
}

static int
actor_new (lua_State* L)
{
Actor *actor = lua_newactor(L);
lua_pushobject(L, actor, ACTOR_LIB);
return 1;
}

static int
actor_print (lua_State* L)
{
Actor *actor = lua_checkactor(L, 1);
lua_pushfstring(L, "%s %p", ACTOR_LIB, actor);
return 1;
}

static const luaL_Reg actor_methods[] = {
{"__tostring", actor_print},
{ NULL, NULL }
};

int
luaopen_Actor (lua_State * L)
{
/* create metatable */
luaL_newmetatable(L, ACTOR_LIB);

/* metatable.__index = metatable */
lua_pushvalue(L, -1);
lua_setfield(L, -1, "__index");

/* register methods */
luaL_setfuncs(L, actor_methods, 0);

/* Actor() => new Actor */
lua_pushcfunction(L, actor_new);

return 1;
}

脚本.c:

#include "common.h"

#define SCRIPT_LIB "Actor.Script"

typedef struct Script {
const char *string;
} Script;

/*
* Allocate a new Script to be passed around.
*/
Script *
lua_newscript (lua_State *L, const char *string)
{
if (string == NULL)
luaL_error(L, "`string` cannot be empty!");

Script *script = (Script*) lua_malloc(L, sizeof(Script));
script->string = string;
return script;
}

/*
* Make sure the argument at index N is a Script and return it if it is.
*/
Script *
lua_checkscript (lua_State *L, int index)
{
return (Script *) luaL_checkudata(L, index, SCRIPT_LIB);
}

static int
script_new (lua_State *L)
{
const char *filename = luaL_checkstring(L, 1);
Script *script = lua_newscript(L, filename);
lua_pushobject (L, script, SCRIPT_LIB);
return 1;
}

static int
script_print (lua_State* L)
{
Script *script = lua_checkscript(L, 1);
lua_pushfstring(L, "%s %p", SCRIPT_LIB, script);
return 1;
}

static const luaL_Reg script_methods[] = {
{"__tostring", script_print},
{ NULL, NULL }
};

int
luaopen_Actor_Script (lua_State *L)
{
/* create metatable */
luaL_newmetatable(L, SCRIPT_LIB);

/* metatable.__index = metatable */
lua_pushvalue(L, -1);
lua_setfield(L, -1, "__index");

/* register methods */
luaL_setfuncs(L, script_methods, 0);

/* Push a function: Script(...) => new script */
lua_pushcfunction(L, script_new);

return 1;
}

通用.h:

#ifndef COMMON
#define COMMON

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

/*
* Allocates size_t memory on the given Lua state.
* lua_newuserdata automatically pushes it, so we pop it.
*/
static
void *
lua_malloc (lua_State *L, size_t size)
{
void *p = lua_newuserdata(L, size);
lua_pop(L, 1);
return p;
}

/*
* Associate an object pointer with given name and push that onto the stack.
*/
static
void
lua_pushobject (lua_State *L, void *object_pointer, const char *metatable_name)
{
lua_pushlightuserdata(L, object_pointer);
luaL_getmetatable(L, metatable_name);
lua_setmetatable(L, -2);
}

#endif

最佳答案

在这种情况下,模块和子模块函数在 C 中是正确的。它遵循 luaopen_Parent_Child_..._Descendant 的形式作为 C 中的函数名称和 Parent.Child.Descendant 在 Lua 中。

这里的问题是我混淆了 lua_pushlightuserdatalua_newuserdata 将什么压入堆栈。 lua_pushlightuserdata 都共享同一个元表,所以我不能有单独的对象。

关于c - 如何在 C 中的 Lua 模块内创建 Lua 模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32673835/

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