如何为LUA创建安全的C接口

McB*_*Bob 0 c lua swig

我正在研究如何在我的应用程序中集成完整的脚本支持,但有一点问题,规划我的C API是LUA友好的.

基本上我有一堆通过init和free函数创建的结构,如下所示:

[test.h]

typedef struct
{
char name[ 50 ];
} Test;


Test *TestAdd( char *name );

Test *TestDelete( Test *test );
Run Code Online (Sandbox Code Playgroud)

[test.c]

Test *TestAdd( char *name )
{
Test *test = ( Test * ) calloc( 1, sizeof( Test ) );

strcpy( test->name, name );

return test;
}


Test *TestDelete( Test *test )
{
free( test );
return NULL;
}
Run Code Online (Sandbox Code Playgroud)

我使用swig生成LUA模块,因此我创建了以下接口文件:

[test.i]

%module test
%{

%}

Test *TestAdd( char *name );

Test *TestDelete( Test * test );
Run Code Online (Sandbox Code Playgroud)

如果用户代码如下所示,一切正常:

a = test.TestAdd( "test" )
a = test.TestDelete( a )

if( a != nil ) print( a.name )
Run Code Online (Sandbox Code Playgroud)

但是如果用户代码是这样的:

a = test.TestAdd( "test" )
test.TestDelete( a )

if( a != nil ) print( a.name ) -- Crash the app with bad_access (not just a LuaVM error).
Run Code Online (Sandbox Code Playgroud)

甚至是最差的:

a = test.TestAdd( "test" )
test.TestDelete( a )
test.TestDelete( a )
-- Another way of making crash my app completely!
Run Code Online (Sandbox Code Playgroud)

有什么方法可以在C中创建一组API来避免这种问题,并允许用户以安全的方式安全地添加/删除和访问属性,不会产生"错误访问"错误并使整个程序崩溃,最好的是LUAVM只返回一个错误并继续执行.

我一直在搜索并尝试不同的方法来我的C API,以避免这个问题,但失败了...

任何人都可以帮助我或给我一些关于这个方向的指示.

提前致谢,

Nic*_*las 5

有一种方法可以做到这一点:停止直接将C风格的接口导出到Lua.C不是Lua,你永远不应该打算让Lua程序像C程序那样行事.

除非没有办法避免它,否则Lua代码永远不必释放任何东西.如果Lua代码明确地创建了某些东西,那么Lua代码应该在其生命周期内具有治理.这意味着你使用垃圾收集来删除内存:当Lua GC完成它时,你使用metamethod来释放你使用的任何调用指针.

通常,您可以通过以下两种方式之一为Lua指定一个对象:Lua 拥有该指针,或者该指针指向一个比lua_State自身更长的对象(因此将始终可用于Lua脚本).在某些情况下,你可以向Lua提供一些它可以引用的临时对象,但是应该尽可能避免这些.

你需要做的是使用该%newobject指令告诉SWIG TestAdd返回一个需要删除的指针.然后,您需要使用%newfree typemapTest对象与TestDelete删除器关联.这将适当地Test将从C的所有权转移到Lua.在这一点,C应该永远手动删除它.让Lua和SWIG完成他们的工作.

因此,TestDelete不应直接暴露给Lua.当GC检测到没有人再引用该Test实例时,将隐式调用它.