C/C++中調用LUA函數(zz)

來源:互聯網
上載者:User

http://hi.baidu.com/darkpaladin/blog/item/00468551e6b67e2542a75bb2.html

[轉]C/C++中調用LUA函數

2007-04-27 11:29

1 配置工作環境

a 下載LUA安裝包 sf_200472410155.zip

b 然後,解壓用於WIN32下的安裝包。放在一個盤的目錄下如:C:/LUA50

c  開啟VC++6.0,點擊Project下的Setting中將include目錄設為C:/LUA50。 並在LIB庫中加入lua+lib.lib ,並將C:/LUA50下的Lua+lib.dll ,Lua+lib.lib拷貝到程式當前所在目錄

【( 風舞影天 的說明:來自www.luachina.net

vc下使用lua都很類似(6.0,2003,2005),如果你能明白一般庫的使用,那麼想要使用lua很簡單
如果是使用純的lua庫(指不使用第三方庫,如luabind,lubplus等),一般你可能會得到三種形式的lua包
1,從www.lua.org下載的源碼包
2,由別人提供的編譯好的lua庫包
3,由別人提供的編譯好的lua動態連結程式庫包
對於第一種包你只需要自己編譯出lua庫然後就可以象第2種方式一樣使用了(實際上第三種包的使用方式只是多了一個步驟)
如何編譯LUA源碼呢?解壓後開啟lua目錄的INSTALL檔案,裡面列出了三個工程
library: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
lmem.c lobject.c lopcodes.c lp***r.c lstate.c lstring.c
ltable.c ltm.c lundump.c lvm.c lzio.c
lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c
ltablib.c lstrlib.c loadlib.c linit.c
interpreter: library, lua.c
compiler: library, luac.c print.c
library,interpreter,compiler,實際上這三個你只需要第一個library,它是讓你能夠將LUA嵌入你的程式的庫, interpreter是解譯器,也就是傳說中的lua.exe,可以把它看成一個使用lua庫的樣本程式,第三個compiler是將lua文本編譯成 lua的二進位格式,所以一般來講,第二和第三個對你來講都不是特別重要或者根本就不會使用到的。
要編譯出這三個庫,你可以開啟你的IDE(指VC),然後建三個工程,把每個工程對應的檔案加入你建立的對應的工程,然後編譯即可產生你庫檔案(*.lib),lua.exe和luac.exe
INSTALL中也提到了可以使用luavs.bat來產生,看看這個批次檔的內容cd src
cl /O2 /W3 /c /DLUA_BUILD_AS_DLL l*.c
del lua.obj luac.obj
link /DLL /out:lua51.dll l*.obj
cl /O2 /W3 /c /DLUA_BUILD_AS_DLL lua.c
link /out:lua.exe lua.obj lua51.lib
cd ..
如果你能看懂它也就知道其實和上面我說的步驟大同小異了(它產生的是動態連結程式庫而不是靜態庫),至於有人說找不到cl.exe,那是因為你的環境變數裡沒 有設定vc的二進位檔案目錄而導致無法找到cl.exe(只要你安裝了VC,那麼是肯定會有這個檔案的)(作為一個程式,如果不知道環境變數這個東東,我 覺得還是有點悲哀哈)
好了,現在你有了標頭檔、庫檔案(或是動態連結程式庫,而動態連結程式庫除了.dll還會提供一個.lib檔案),那麼剩下的事情就是如何將LUA嵌入你的程式中了。
首先是在你使用到LUA函數的地方你肯定要#include ,而實際上lua有三個標頭檔,lua.h, lualib.h,lauxlib.h,你可以開啟這些標頭檔查看有那些LUA API(lua5.x改變了lua4.x的一些函數名,只不過lua5.0.2使用了一些宏來相容以前的函數名,而5.1.1則去除掉了這些宏,你可以查 看這些標頭檔來看那些API函數名已經改掉了,比較常見的是lauxlib.h)
ps:使用C++的同學別忘了你連結庫採用的代碼產生方式是C++還是C,因為C++最終會改變其函數名(如lua_open改成 lua_open@4),一般都是選擇產生C的代碼產生方式,因為不同的C++編譯器改變的函數名規則是很可能不同的,至於為什麼會改名想想函數重載,具 體的去GOOGLE吧。而如果你編譯連結庫時採用的是C代碼產生方式,別忘了在#include時加上extern "C"
當然你僅僅包含了標頭檔是肯定會出現連結錯誤的,因為在連結的時候無法找到對應函數的代碼,而這些代碼都包含在靜態庫檔案*.lib中(或是動態連結程式庫的*.dll中),VC中加入連結庫檔案有兩種方式,一是工程裡設定,二是使用
#pragma comment(lib,"****.lib")
)】
例一:
main.cpp
//--------------------------------------------------
#include <stdio.h>

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

/* LUA介面聲明*/
lua_State* L;

int main ( int argc, char *argv[] )
{
/* 初始化 Lua */
L = lua_open();

/*載入LUA庫 */
lua_baselibopen(L);

/* 運行LUA指令碼 */
lua_dofile(L, "test.lua");

/* 清除 Lua */
lua_close(L);

return 0;
}

指令碼test.lua:
用記事本寫入以下代碼,改副檔名為lua即可
-- simple test

print "Hello, World!"
例2:
首先用記事本寫個Lua檔案。

----fun.lua--------
function add ( x, y )
return x + y
end

在前面的教程,調用lua_dofile()將執行指令碼。
本章裡,指令碼定義為一個函數。
用lua_dofile()只簡單的使這個函數在我們的程式中變為有效。

LUA的函數可以接收多個參數,並可以返回多種類型的結果,這

裡使用了堆棧。

       為了調用一個LUA函數,我們首先要把函數壓棧。
這個函數的結果由參數決定,所以,我們要調用函數將需要
lua_call(),調用這個函數之後,返回的結果將在堆棧中存在。

整個步驟:
1.用lua_getglobal()把add函數放入堆棧
2.用lua_pushnumber()把第一個參數壓入堆棧
3.用lua_pushnumber()把第二個參數壓入堆棧
4.用lua_call()調用函數。
5,現在用lua_tonumber從堆棧頭取出結果
6,最後用lua_pop從堆棧中移除結果值。

代碼:luaadd.cpp
如果你喜歡用C代替C++,改名為luaadd.c,並且除去
extern "C"即可
#include <stdio.h>

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

/* the Lua interpreter */
lua_State* L;

int luaadd ( int x, int y )
{
int sum;

/* the function name */
lua_getglobal(L, "add");

/* the first argument */
lua_pushnumber(L, x);

/* the second argument */
lua_pushnumber(L, y);

/* call the function with 2
      arguments, return 1 result */
lua_call(L, 2, 1);

/* get the result */
sum = (int)lua_tonumber(L, -1);
lua_pop(L, 1);

return sum;
}

int main ( int argc, char *argv[] )
{
int sum;
/* initialize Lua */
L = lua_open();

/* load Lua base libraries */
lua_baselibopen(L);

/* load the script */
lua_dofile(L, "add.lua");
/* call the add function */
sum = luaadd( 10, 15 );

/* print the result */
printf( "The sum is %d\n", sum );

/* cleanup Lua */
lua_close(L);

return 0;
}
二:lua中調用c函數
我們用C/C++建立一個函數並告訴Lua解譯器,然後在Lua中調用這個函數並使用函數的傳回值。
定義一個C/C++函數:
要想C/C++中的函數能被Lua調用,函數定義必須這樣:
代碼:typedef int (*lua_CFunction) (lua_State *L);
也就是說,函數必須以Lua解譯器作為參數,並且傳回值為int類型。既然Lua解譯器作為函數的參數,那麼實際上函數可以從棧中取得任意多個參數。下面 我們將看到,返回的整數值代表入棧的值的數目。如果有一個C/C++函數,你想在Lua中調用他,很容易封裝一下就可以滿足上述要求。
下面的C++的average函數例子中,可以清楚地看到Lua中調用C/C++函數是如何?的。
1. lua_gettop()返回棧頂的下標索引,由於Lua中棧的下標從1開始,這個傳回值實際上也就是函數參數的個數。
2. For迴圈計算各個參數總和。
3. Average的參數是通過調用lua_pushnumber()入棧的。
4. 然後參數之和被入棧。
5. 最後,函數傳回值為2,表明有兩個傳回值,並且已經入棧。
函數被定義之後,我們必須告訴Lua編譯器他的存在,這在main()函數中,在Lua解譯器被初始化,類庫載入之後完成的。
將下面的代碼儲存為luaavg.cpp,如果你喜歡用C而不是C++,需要儲存檔案為luatest.c並且把extern去掉。
#include <stdio.h>
extern "C" {
       #include "lua.h"
       #include "lualib.h"
       #include "lauxlib.h"
}
/* the Lua interpreter */
lua_State* L;
static int average(lua_State *L)
{
       /* get number of arguments */
       int n = lua_gettop(L);
       double sum = 0;
       int i;
       /* loop through each argument */
       for (i = 1; i <= n; i++)
       {
           /* total the arguments */
           sum += lua_tonumber(L, i);
       }
       /* push the average */
       lua_pushnumber(L, sum / n);
       /* push the sum */
       lua_pushnumber(L, sum);
       /* return the number of results */
       return 2;
}
int main ( int argc, char *argv[] )
{
       /* initialize Lua */
       L = lua_open();
       /* load Lua base libraries */
       lua_baselibopen(L);
       /* register our function */
       lua_register(L, "average", average);
       /* run the script */
       lua_dofile(L, "avg.lua");
       /* cleanup Lua */
       lua_close(L);
       return 0;
}
下面是一個簡單的Lua指令碼:
-- simple test
代碼print "Hello, World!"
確認它能運行。
編譯:
使用你喜歡的編譯器編譯上面儲存的C/C++檔案,下面以Linux為例:
命令列鍵入:
代碼:g++ luatest.cpp -llua -llualib -o luatest
如果沒有錯誤的話,運行程式:
代碼:./luatest
程式應該列印出:Hello, World!
如果你不是Linux作業系統,使用的是Vc++編譯器,你需要:
1. 建立一個新的win32控制台應用工程。
2. 將檔案luatest.cpp添加到你的工程中。
3. 到Project, Settings點擊Link頁。
4. 添加lua+lib.lib到Object/library modules列表中。
5. 按F7編譯器。
運行程式以前,你需要確保lua+lib.dll檔案放在windows可以找到的地方,將這個檔案從C:\Program Files\Lua-5.0拷貝到Visual C++ project目錄,如果編譯沒有錯誤的話,現在可以Ctrl+F5運行程式了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.