close

另一方面,我們可能更常使用lua去調用c函式。
例如:LÖVE - Free 2D Game Engine,便是使用lua來調用LÖVE的物件。
通常我們都會把較注重效率的部分寫成c函式,其他的流程與邏輯用lua寫成。
如此一來有兩個好處:不必每次都要重新編譯、可以快速的測試程式。
而這也是「組件式設計」的核心概念,與Plug in有點類似。

-------

Part 2 - 在
lua中調用c/c++函數

提供給lua調用的c函式都長一個樣:

static int Func( lua_State* L )
{
    //do something
    return 回傳值的數量
}

在這裡c函式的return值,代表的是該函式提供給lua調用時return值的數量,
因為lua函式支援不定數的回傳值,而c函式的回傳值至多一個。

#include <cstdio>
#include <cstdlib>
#include "Lua/lua.hpp"
#pragma comment( lib, "Lua/lua51.lib" )

lua_State* ls ;

//提供給lua調用的函式
static int Fibonacci( lua_State* L )
{
int argc = lua_gettop( L ) ; //總共的參數個數
int n = (int)lua_tonumber( L , 1 ) ; //取得第一個參數
//這個Fibonacci函式剛好只有一個參數

//fibonacci演算的主體
int last = 1, next_last = 0 ;
int answer = 1 ;

if( n <= 1 ) {
lua_pushnumber( L, (double)last ) ;
return 1 ; //這個lua函式回傳值只有一個
}

for( int i = 2 ; i <= n ; ++i ) {
answer = last + next_last ;
next_last = last ;
last = answer ;
}
//演算結束

//return answer傳給lua
lua_pushnumber( L, (double)answer ) ;
return 1 ; //這個lua函式回傳值只有一個
}

int main( int argc, char** argv )
{
ls = lua_open() ;
luaopen_base( ls ) ;
luaL_openlibs( ls ) ;

//向lua註冊一個c函式
lua_register( ls, "Fibonacci", Fibonacci ) ;
luaL_dofile( ls, "fibonacci.lua" ) ; //執行

lua_close( ls ) ;
system( "PAUSE" ) ;
return 0 ;
}


從main函式看起,會發現多了個lua_register,
這個lua api是向lua註冊一個函式供它調用,至於註冊名是否要和c函式一樣,
這就看各人喜好了,並無強制規定。

然後再看Fibonacci函式,
因為呼叫函式的是lua,c並不知道有多少個參數,所以要用lua_gettop從lua的堆疊頂端中取得參數量。
接著就可以很簡單的用lua_tonumber、lua_tostring等api,把參數從lua抓到c的函式中。
等運算完畢後,
再把結果lua_pushnumber、lua_pushstring,傳給lua就可以了。

Fibonacci.lua

n = 10
print( "This is lua to call C function!" )
print( "Fibonacci("..n..") = "..Fibonacci(n) ) 

lua中只須短短的3句。 

ps.
如果有出現以下的訊息:
fatal error C1047: 物件或程式庫檔案 'lua51.lib' 是使用比其他物件更舊的編譯器建立的,請重建舊物件和程式庫

這是因為對方使用舊版的vc去編譯lib
vc中的libcmt.lib、msvcrt.lib,似乎每版都有些許差別。

解決方法有兩種:
1. 去Lua官網下載原始碼自己編譯,或者下載適合自己的binary file
2. vc的專案屬性→C/C++→最佳化→整個程式最佳化→否

 

arrow
arrow
    文章標籤
    Lua C/C++ 調用函數
    全站熱搜

    鴉 發表在 痞客邦 留言(0) 人氣()