2011-12-16 55 views
0

我正在研究如何将完整的脚本支持集成到我的应用程序中,但在计划我的C API成为LUA友好程序时遇到了一些问题。如何为LUA创建安全的C接口

基本上我得到了通过init和免费 功能创建这样结构的一串:

[test.h]

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


Test *TestAdd(char *name); 

Test *TestDelete(Test *test); 

[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; 
} 

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

[test.i]

%module test 
%{ 

%} 

Test *TestAdd(char *name); 

Test *TestDelete(Test * test); 

一切都正常工作,如果用户代码是这样的:

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

if(a != nil) print(a.name) 

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

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

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

甚至最差:

a = test.TestAdd("test") 
test.TestDelete(a) 
test.TestDelete(a) 
-- Another way of making crash my app completely! 

有没有我可以在C中创建一组API来避免这种问题,并且可以让用户以安全的方式安全地添加/删除和访问属性,从而不会产生“不良访问”错误并使整个程序崩溃,最好的办法就是LUAVM只是返回一个错误并继续执行。

我一直在寻找和尝试不同的方法,我的C API来避免这个问题,但失败了......

任何人都可以帮助我或者给我一些指点关于要去的方向与此有关。

由于提前,

+0

如果您可以将指针设置为NULL,那么将它释放两次不会成为问题,您只需在每个使用它的函数中检查它是否为NULL即可。 – 2011-12-16 02:48:37

回答

5

有一种方法可以做到这一点:停止直接出口C-风格的界面到Lua。 C不是Lua,你也不应该让Lua程序像C程序那样行事。

除非无法避免它,否则Lua代码不应该释放任何东西。如果Lua代码明确地创建了一些东西,那么Lua代码应该在其生命周期中进行治理。这意味着你使用垃圾收集来删除内存:当Lua GC完成它时,你可以使用一个元方法来释放指针,而不管你使用什么调用。

在一般情况下,你给Lua的一个指向对象以两种方式之一:要么Lua的拥有该指针,或指针指向的对象,将活得比的lua_State本身(因此将永远是提供给Lua脚本)。在某些情况下,你可能会向Lua提交一些它可以引用的临时对象,但是应尽可能避免这些临时对象。

你需要做的是use the %newobject directive告诉SWIG TestAdd返回一个需要删除的指针。然后,您需要将Test对象与TestDelete作为删除者,using %newfree typemap。这将把C的Test的所有权转让给Lua。在这一点上,C应该从来没有手动删除它。让Lua和SWIG完成他们的工作。因此,TestDelete不应直接暴露给Lua。当GC检测到没有人指向Test实例时,它将被隐式调用。

+0

嗡嗡声我不知道我得到它,你能创建一个简单的例子,我上面发布的代码?从你重定向我的页面我觉得: %newobject create_foo; %delobject destroy_foo; ... Foo * create_foo(); void destroy_foo(Foo * foo); 会走的路吗?但我仍然不知道我可以执行此... – McBob 2011-12-16 04:09:11