lua與C/C++互調函式方法
lua與C/C++互調函式方法
1.在lua指令碼中呼叫C/C++程式碼中的函式
C/C++函式定義形式
lua中呼叫的C++函式的定義必須滿足如下形式: typedef int(*lua_cFunction)(lua_State *L);
函式引數必須是lua_State,返回值必須是int型,只有這樣的函式Lua才能呼叫。
C函式引數獲取設定協議
C函式中的引數通過Lua中堆疊L來接收到,引數以正序入棧,第一個引數首先入棧。第一個引數的索引是1,最後一個引數的索引就是引數個數。C函式剛開始處,沒有進行棧中資料pop、push操作之前,lua_gettop(L)可以返回函式接收到的引數個數。
C函式向lua中返回值
需要向lua返回值,可以通過把需要返回的值以正序方式壓入棧即可(第一個返回值首先壓入)。
C函式的返回值
C函式的返回值(int型別)= C函式向lua中返回的值個數(壓入棧的變數個數)
例子
接收若干數字引數,並返回它們的平均數與和:
#include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #include // lua是用純C語言寫的 #include #include #ifdef __cplusplus } #endif /* __cplusplus */ int c_average(lua_State* L) { int n = lua_gettop(L); /* 返回棧頂元素的索引。因為索引是從1開始編號的(1表示棧底,-1表示棧頂),所以這個結果等於堆疊上的元素個數(返回0表示堆疊為空)。這裡棧中元素的個數就是傳入的引數個數 */ double sum = 0; int i; for (i = 1; i <= n; i++) { if (!lua_isnumber(L, i)) { lua_pushstring(L, "Incorrect argument to 'average'"); // 將錯誤資訊壓入棧中 lua_error(L); // 丟擲棧頂的錯誤 /* int lua_error (lua_State *L); 產生一個 Lua 錯誤。錯誤資訊(實際上可以是任何型別的 Lua 值)必須被置入棧頂。這個函式會做一次長跳轉,它不會再返回。 */ } sum += lua_tonumber(L, i); // lua_tonumber 將棧中指定index的值轉換成數值型別的值,注意並不會從棧中彈出這個值 } double avg = sum / n; lua_pushnumber(L, avg); // 將avg壓入棧中,第1個返回值是avg lua_pushnumber(L, sum); // 將sum壓入棧中,第2個返回值是sum return 2; /* return the number of results,該函式有2個返回值,即上面入棧的avg和sum */ } int main(int argc, char* argv[]) { lua_State* L = luaL_newstate(); // 建立一個新的獨立的狀態機 /* register our function,告訴lua指令碼其中呼叫的average函式(lua中的變數名)對應的是一個叫c_average的c語言函式 */ lua_register(L, "average", c_average); /* void lua_register (lua_State *L, const char *name, lua_CFunction f); 把 C 函式 f 設到全域性變數 name 中。它通過一個巨集定義: #define lua_register(L,n,f) \ (lua_pushcfunction(L, f), lua_setglobal(L, n)) */ /* run the script */ luaL_dofile(L, "e1.lua"); // 載入指令碼,指令碼中的可執行語句將會得到執行 /* Loads a file as a Lua chunk and then 以保護模式呼叫一個函式,等價於(luaL_loadfile(L,filename) || lua_pcall(L, 0, LUA_MULTRET, 0)) */ lua_getglobal(L, "avg"); // 將全域性變數avg的值入棧,等價於lua_getfield(L,LUA_GLOBALSINDEX, "name”);此時el.lua中avg變數已經有值,等於把這個變數的值壓入棧。 printf("avg is: %d\n", lua_tointeger(L, -1)); // 讀棧頂的int值,注意不會從棧中彈出這個元素 lua_pop(L, 1); // 彈出棧頂的一個元素 lua_getglobal(L, "sum"); // 將全域性變數sum的值入棧 printf("sum is: %d\n", lua_tointeger(L, -1)); lua_pop(L, 1); // 彈出棧頂的一個元素 /* cleanup Lua */ lua_close(L); return 0; } /* -- e1.lua avg, sum = average(10, 20, 30, 40, 50) print("The average is ", avg) print("The sum is ", sum) */ /* 輸出: The average is 30 The sum is 150 avg is: 30 sum is: 150 */
2.在C/C++程式碼中呼叫lua指令碼中的函式
核心步驟:在C/C++中將使用的lua函式名以及其函式引數一次壓入棧中(引數按正序入棧),返回值由lua按正序自動壓入棧供C/C++訪問。函式呼叫成功後,函式名、引數出棧,返回值自動入棧(不需要手動寫壓入棧程式碼)。
示例:
#include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #include // lua是用純c語言寫的 #include #include #ifdef __cplusplus } #endif /* __cplusplus */ lua_State* L = NULL; int luaAdd(int x, int y) { int sum; /* the function name,lua指令碼中的函式名 */ lua_getglobal(L, "add"); // lua函式名入棧 int savedTop = lua_gettop(L); // 儲存棧中的元素個數,後面要還原 /* the first argument */ lua_pushnumber(L, x); // 引數x入棧 /* the second argument */ lua_pushnumber(L, y); // 引數y入棧 // 此時棧中有3個值,棧頂是引數y,棧底是函式名add /* call the function with 2 arguments, return 1 result */ lua_call(L, 2, 1); // 因為add只有一個返回值,所以此時棧中只有1個值(如果有多個返回值,也是按正序入棧) /* get the result */ sum = (int) lua_tonumber(L, -1); // -1是棧頂 lua_settop(L, savedTop); // 函式退出之前恢復原來的棧 return sum; } int main(int argc, char* argv[]) { L= luaL_newstate(); // 建立lua執行環境 /* load the script,載入指令碼,為後面讀取其中的變數做準備 */ luaL_dofile(L, "e2.lua"); /* call the add function */ int sum = luaAdd(10, 15); /* print the result */ printf("The sum is %d\n", sum); /* cleanup Lua */ lua_close(L); return 0; } -- e2.lua -- add two numbers function add(x, y) return x + y end The sum is 25
3. LUAJIT_MODE_ON
lua_pushlightuserdata(m_luastack, (void*) script_exception_wrapper);
luaJIT_setmode(m_luastack, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
int script_exception_wrapper(lua_State *L, lua_CFunction f)
{
try {
return f(L); // Call wrapped function and return result.
} catch (constchar *s) { // Catch and convert exceptions.
lua_pushstring(L, s);
} catch (LuaError& e) {
lua_pushstring(L, e.what());
}
returnlua_error(L); // Rethrow as a Lua error.
}
LUAJIT_MODE_ON時,執行lua中函式,當呼叫C/C++函式時,會跳到script_exception_wrapper然後通過f(L)再跳到lua函式名對應的CFuntion;此模式必須使用lua_pushlightuserdata同時執行一個script_exception_wrapper指標函式;包裝器功能可以用於除錯目的,也可以用於捕獲和轉換外部異常。建議使用
lightuserdata使用時,只儲存了函式指標,不需要儲存真實資料,減少了記憶體使用。
LUAJIT_MODE_OFF時,執行lua中函式,當呼叫C/C++函式時,會直接跳到lua函式名對應的CFuntion;
參考資料:
http://blog.csdn.net/rain_qingtian/article/details/44781183
http://blog.csdn.net/ly131420/article/details/8794615
http://luajit.org/ext_c_api.html
http://dev.minetest.net/Script_Engine
相關推薦
lua與C/C++互調函式方法
lua與C/C++互調函式方法 1.在lua指令碼中呼叫C/C++程式碼中的函式 C/C++函式定義形式 lua中呼叫的C++函式的定義必須滿足如下形式: typedef int(*lua_cFunction)(lua_State *L);
C/C++與lua互調函式的方法
1,在lua指令碼中呼叫C/C++程式碼中的函式 在C++中定義函式時必須以lua_State為引數, 以int為返回值才能被Lua所呼叫。 /* typedef int (*lua_CFunction) (lua_State*L); C 函式的型別。 為了正確的和 Lu
golang go語言與C語言互調,通過cgo
1. good links: http://tonybai.com/2012/09/26/interoperability-between-go-and-c/ http://www.mischiefblog.com/2014/06/26/example-cgo-golang
C#呼叫C帶回調函式方法的實現
1、C語言定義個回撥函式的註冊 typedef void(__stdcall *test_callback)(int* array, int size); __declspec(dllexport)
C++ 編寫回調函式步驟
簡單幾步驟 void callback_func(void *userdata, const char*, uint32_t len) { //回撥函式內容 } typedef void(*ca
js字元與ASCII碼互轉的方法
大寫字母A-Z對應的ASCII碼值是65-90 小寫字母a-z對應的ASCII碼值是97-122 將字母轉為ascii嘛的方法: var str = "A"; str.charCodeAt(); // 65 var str1 = 'a'; str1.charCodeAt()
iOS原生介面與RN介面互調及傳值
文章目錄 3. iOS原生與RN互調及傳值 3.1 RN跳轉原生介面 3.2 RN跳轉原生介面並傳值 3.3 RN跳轉原生介面並傳值後,原生介面再回調給RN介面相關資訊 3. 4. 原生頁面向RN頁面傳值
c#後臺呼叫前臺與js方法互調
很多人都向在伺服器端呼叫客戶端的函式來操作,也就是在asp中呼叫javascript指令碼中已經定義好的指令碼函式。經過研究,發現了一些勉強的方法。 1. 用Response.Write方法寫入指令碼 比如在你單擊按鈕後,先操作資料庫,完了後顯示已經完成,可以在最後想呼叫的地
Tolua使用筆記二:lua與C#的函式,變數互動方法
接著上一回的接著講: 案例三: 到這裡久終於到了大家最感興趣的地方了,熱更新的價值就在於用指令碼語言寫邏輯,這樣可以實現邏輯的頻繁改動而不用每次更新都重新下載。 而這個過程中必然涉及到C#對lua的一個邏輯呼叫,而這個例子實現的就是C#的函式的呼叫 核心程式碼如下:
Lua 與C/C++ 交互系列:註冊枚舉enum到Lua Code中
mon size main 空間 log 方便 我們 .cpp lua 在Lua Code中註冊C/C++的枚舉很easy,就像註冊全局變量一樣。我們使用枚舉名稱作為命名空間,來避免註冊的枚舉發生沖突。註冊的枚舉存儲在全局環境(線程環境)中。 當在Lua Code中
C#在WinForm中使用WebKit傳遞js對象實現與網頁交互的方法
復制代碼 dll ssa 所有 添加 spa load net clas 這篇文章主要介紹了C#在WinForm中使用WebKit傳遞js對象實現與網頁交互的方法,涉及針對WebBroswer控件及WebKit控件的相關使用技巧,需要的朋友可以參考下 本文實例講述了C#在W
lua與C交互關鍵函數
const lua_next 素數 font con tab 成功 create 參數 1、lua_next(L, t_idx) 參數解釋: L:虛擬機 t_idx:table在棧中索引 返回 int:0執行失敗;非0執行成功
lua 與 c/c++ 互動(6) lua呼叫C++(使用陣列 和字串函式)
lua呼叫 c++ 的 兩個函式: 一個是 對lua 陣列 呼叫函式替換 陣列元素,一個 分割字串 test.lua --陣列操作 a = {1,2,3,4,5,6} swapArray(a,function(t) return t + 1 end) local
C++與Lua進資料交換的工具函式
1)tolua.type 返回一個 C++ 物件的型別描述字串 格式: self.studio.layout = cc.CSLoader:createNode(GAMETABLE_CSB); print(tolua.type(self.studio.layout))
Lua 與C/C++ 互動系列:通過C呼叫Lua函式(1)
1、Lua通過ANSI C 進行編寫,Lua與C互動要遵循一定的協議規則。在Lua 5.1 Reference Manual中明確規定如何通過C Code呼叫Lua 編寫的函式。 C code可以呼叫Lua Code編寫的任何函式.本文主要以全域性函式來做演示
C/C++與Lua之間進行資料函式互動以及解決“PANIC: unprotected error in call to Lua API (attempt t
在使用Cocos2d-x 時候,難免需要C/C++呼叫Lua函式、資料或Lua呼叫C/C++函式,那麼本篇講詳細介紹C/C++與Lua之間的資料、函式互動。 首先讓我們來簡單瞭解幾個Lua API函式: int luaL_dofile (lua_Sta
C語言 在被調函式中改變指標變數值的方法
先看一段程式碼: #include <iostream> void foo(char *p) { p = "after foo()"; } void main() { char *p = "before foo()"; foo(
lua 與c++互動 之呼叫函式
</pre><pre name="code" class="cpp"> 對c/c++ 與lua的互動呼叫函式做一個小總結 #include <iostream>
C/C++ 常用的函式與方法
1,建立多級目錄 #include <string> #include <direct.h> //_mkdir函式的標頭檔案 #include <io.h> //_access函式的標頭檔案 using name
C# 中物件與Json互轉的方法整理筆記
前言 原先一直做CS的開發,對Json瞭解不多,最近轉做BS後,才接觸到了Json。作為後臺與前端頁面資料互動的基礎,Json的地位非常重要,自然而然Json轉換方法的重要性也不言面喻。 最開始使用的是同事原來寫好的物件轉Json的方法,並沒有什麼問題,