Lua和C 語言的互動詳解

2021-07-10 17:27:55 字數 3403 閱讀 9993

前言

寫過windows程式的人都知道,對於應用程式,如果需要在本地儲存一些配置資訊,我們經常將這些配置資訊寫在登錄檔或者本地的配置檔案中,很多應用都是將一些配置資訊寫在配置檔案中,比如以ini結尾的檔案,這種配置檔案很多,使用的很廣泛,然後應用程式在啟動的時候,就會解析這個配置檔案,讀取一些配置資訊。

lua的一項重要用途就是作為一種配置語言。而這篇文章將結合lua來擴充套件應用程式,這種方式提供了更大的靈活性和便利性。

這篇博文主要總結的是使用c++和lua進行互動,涉及到獲取lua中普通變數的值,lua中table的值和呼叫lua中的函式。下面就開始吧。

從乙個最簡單的例子開始

複製**

**如下:

bool cluaconfig::loadconfig()

// 載入配置檔案

int bret = lual_loadfile(l, pconfigfile);

if (bret)

// 執行配置檔案

bret = lua_pcall(l, 0, 0, 0);

if (bret)

// 讀取高

lua_getglobal(l, "width");

lua_getglobal(l, "height");

// width

if (!lua_isnumber(l, -2))

// height

if (!lua_isnumber(l, -1))

iwindowheight = lua_tointeger(l, -1);

iwindowwidth = lua_tointeger(l, -2);

return true; }

table操作

在lua中,對於table這種bug一樣存在的東西,如果c api無法操作table,那我們還能不能愉快的玩耍了。讓我們來看看c api如何操作table。現在有如下lua語句:

複製**

**如下:

background =

那麼,c api如何讀取這段**,將其中的每個欄位都解析出來呢。我先把**貼上來,然後一句一句的分析:

複製**

**如下:

// 讀取全域性的資料到棧中

lua_getglobal(l, "background");

if (!lua_istable(l, -1))

// 讀取table中字段的值,將值壓入棧中

lua_getfield(l, -1, "r");

// 讀取棧中的值

if (!lua_isnumber(l, -1))

double fvalue = lua_tonumber(l, -1);

cout << "r => " << fvalue << endl;

原諒我省略了lual_newstate這樣的**。好了,讀取乙個table,同讀取乙個全域性的變數是乙個道理的。分為以下幾步:

1.使用lua_getglobal讀取這個變數,將table讀取到棧中;

2.使用lua_getfield讀取table中字段的值,將字段的值讀取到棧中;

3.使用lua_to*系列函式,將字段的值從棧中讀取出來。

這是讀取table的操作,那設定table的操作呢?我們可以將我們自己的值寫入到棧中,這該怎麼操作?看**:

複製**

**如下:

// 將需要設定的值設定到棧中

lua_pushnumber(l, 0.55);

// 將這個值設定到table中

lua_setfield(l, -2, "r");

就是上面兩行**,當然了,你也需要先使用lua_getglobal讀取table變數,將table讀取到棧中,然後按照上面的兩行**進行設定就ok了。上面兩行**的具體含義是什麼呢?

1.lua_push*系列函式是將乙個需要設定的新值放到棧中;

2.lua_setfield函式同lua_getfield是乙個性質的函式,只不過這裡是set語義,將lua_push*到棧中的值,設定到table對應的key中。

現在讀取table,設定table都說了,那如何在表中完全建立乙個新的table呢?我們有這種需求。怎麼辦?

複製**

**如下:

// 建立乙個新的table,並壓入棧

lua_newtable(l);

// 往table中設定值

lua_pushstring(l, "

"); // 先將值壓入棧

lua_setfield(l, -2, "website"); // 將值設定到table中

// 再設定乙個值

lua_setfield(l, -2, "description");

呼叫lua函式

是的,你沒有看錯,你可以在一lua檔案中定義乙個函式,然後在c++中呼叫這個函式,貌似「高大上」的感覺。現在我就來說說這個「高大上」的功能;習慣性的上**:

複製**

**如下:

// 再來看看有引數和返回值得函式呼叫

// 現在在test.lua中定義了乙個add函式,計算兩個值的和,這兩個值就是用引數傳進去的

// 得到和以後,會返回這個和,現在我們就在c++這邊呼叫這個add函式

lua_getglobal(l, "add"); // 獲取函式,壓入棧中

lua_pushnumber(l, 10); // 壓入第乙個引數

lua_pushnumber(l, 20); // 壓入第二個引數

// 完成呼叫

iret = lua_pcall(l, 2, 1, 0);

if (iret)

// 獲得計算結果

iret = lua_isnumber(l, -1);

if (!iret)

double fvalue = lua_tonumber(l, -1);

cout << "result is " << fvalue << endl;

上面**是呼叫以下lua函式:

複製**

**如下:

-- 有引數,有返回值

function add(ia, ib)

return ia + ib

end這個簡單的lua函式沒有任何講的地方,說說上面的那一長段c++**吧。在lua中,函式和普通的值是一樣的,所以,c++呼叫lua中的函式,分為以下幾步:

使用lua_getglobal來獲取函式,然後將其壓入棧;

如果這個函式有引數的話,就需要依次將函式的引數也壓入棧;

這些準備工作都準備就緒以後,就呼叫lua_pcall開始呼叫函式了,呼叫完成以後,會將返回值壓入棧中;

最後取返回值得過程不用多說了,呼叫完畢。

總結

Lua和C語言的互動(一)

lua生來就是為了和c互動的,因此使用c擴充套件lua或者將lua嵌入到c當中都是非常流行的做法。要想理解c和lua的互動方式,首先要回顧一下c語言是如何處理函式引數的。c函式和引數 大家知道c語言是用彙編實現的,在組合語言中可沒有函式的概念,與函式對應的是叫做子過程的東西,子過程就是一段指令,乙個...

Lua和C語言的互動(一)

lua生來就是為了和c互動的,因此使用c擴充套件lua或者將lua嵌入到c當中都是非常流行的做法。要想理解c和lua的互動方式,首先要回顧一下c語言是如何處理函式引數的。c函式和引數 大家知道c語言是用彙編實現的,在組合語言中可沒有函式的概念,與函式對應的是叫做子過程的東西,子過程就是一段指令,乙個...

Lua和C語言的互動 C API

lua可作為擴充套件性語言 lua可以作為程式庫用來擴充套件應用的功能 同時也是個可擴充套件的語言 lua程式中可以註冊由其他語言實現的函式 c和lua互動的部分稱為c api。c api是乙個c 與lua進行互動的函式集。他由以下部分組成 讀寫lua全域性變數的函式 呼叫lua函式的函式 執行lu...