Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何为LUA创建安全的C接口_C_Lua_Swig - Fatal编程技术网

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

如何为LUA创建安全的C接口,c,lua,swig,C,Lua,Swig,我正在研究如何在我的应用程序中集成完整的脚本支持,但是在规划我的C API以使其对LUA友好时遇到了一些问题 基本上我得到了一堆通过init和free创建的结构 功能如下: a = test.TestAdd( "test" ) a = test.TestDelete( a ) if( a != nil ) print( a.name ) [测试h] typedef struct { char name[ 50 ]; } Test; Test *TestAdd( char *name );

我正在研究如何在我的应用程序中集成完整的脚本支持,但是在规划我的C API以使其对LUA友好时遇到了一些问题

基本上我得到了一堆通过init和free创建的结构 功能如下:

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

if( a != nil ) print( a.name )
[测试h]

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


Test *TestAdd( char *name );

Test *TestDelete( 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;
}
Im使用swig生成LUA模块,因此我创建了以下接口文件:

[测试一]

%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方法,但失败了

任何人都可以帮助我,或者给我一些关于这个方向的建议


提前感谢,

有一种方法可以做到这一点:停止将C风格接口直接导出到Lua。C不是Lua,您永远不应该让Lua程序像C程序一样工作

除非无法避免,否则Lua代码永远不应该释放任何东西。如果Lua代码显式地创建了一些东西,那么Lua代码应该在其生命周期中拥有治理权。这意味着您可以使用垃圾收集来删除内存:当Lua-GC完成它时,您可以使用元方法来释放指针,无论您使用什么调用

通常,可以通过以下两种方式之一为Lua提供指向对象的指针:Lua拥有该指针,或者该指针指向的对象将超过
Lua_状态本身(因此Lua脚本始终可用)。在某些情况下,您可能会向Lua提供一些它可以引用的临时对象,但应尽可能避免这些情况

您需要做的是告诉SWIG,
TestAdd
返回一个需要删除的指针。然后,您需要将
Test
对象与
TestDelete
关联为删除器。这将正确地将
测试的所有权从C转移到Lua。在这一点上,C永远不应该手动删除它。让Lua和SWIG做他们的工作


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

有一种方法可以做到这一点:停止将C风格接口直接导出到Lua。C不是Lua,您永远不应该让Lua程序像C程序一样工作

除非无法避免,否则Lua代码永远不应该释放任何东西。如果Lua代码显式地创建了一些东西,那么Lua代码应该在其生命周期中拥有治理权。这意味着您可以使用垃圾收集来删除内存:当Lua-GC完成它时,您可以使用元方法来释放指针,无论您使用什么调用

通常,可以通过以下两种方式之一为Lua提供指向对象的指针:Lua拥有该指针,或者该指针指向的对象将超过
Lua_状态本身(因此Lua脚本始终可用)。在某些情况下,您可能会向Lua提供一些它可以引用的临时对象,但应尽可能避免这些情况

您需要做的是告诉SWIG,
TestAdd
返回一个需要删除的指针。然后,您需要将
Test
对象与
TestDelete
关联为删除器。这将正确地将
测试的所有权从C转移到Lua。在这一点上,C永远不应该手动删除它。让Lua和SWIG做他们的工作


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

如果您可以将指针设置为
NULL
,那么
free
两次将不会有问题,您只需在使用它的每个函数中检查它是否
NULL
。如果您可以将指针设置为
NULL
那么
free
两次就不会有问题了,你只需要检查使用它的每个函数中的
NULL
。嗯,我不确定我是否得到了它,你能用我上面发布的代码创建一个简单的例子吗?从您重定向我的页面中,我感觉到:%newobject create\u foo;%删除对象销毁\u foo。。。Foo*创建_Foo();无效销毁_foo(foo*foo);那是去的路吗不?但是我仍然不知道我能不能实现这个…@McBob:很抱歉链接;我已经改正了。但是,正如我所说的,不要向用户公开
TestDelete
。我不知道你没有得到什么,因为SWIG文档非常全面。如果你不明白SWIG类型映射和选项是如何工作的,你应该先弄清楚。嗯,我不确定我是否明白,你能用我上面发布的代码创建一个简单的例子吗?从您重定向我的页面中,我感觉到:%newobject create\u foo;%删除对象销毁\u foo。。。Foo*创建_Foo();无效销毁_foo(foo*foo);那是去的路吗不?但是我仍然不知道我能不能实现这个…@McBob:很抱歉链接;我已经改正了。但是,正如我所说的,不要向用户公开
TestDelete
。我不知道你没有得到什么,因为SWIG文档非常全面。如果您不了解SWIG类型映射和选项是如何工作的,您应该首先弄清楚这一点。