2011-12-16 54 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