1. 程式人生 > >C++程式設計知識:Lua 和 C/C++ 互相呼叫例項分析

C++程式設計知識:Lua 和 C/C++ 互相呼叫例項分析

lua作為小巧精悍的指令碼語言,易於嵌入c/c++中 , 廣泛應用於遊戲AI ,實際上在任何經常變化的邏輯上都可以使用lua實現,配合c/c++實現的底層介面服務,能夠大大降低系統的維護成本。下面對lua和c/c++的互動呼叫做一個例項分析:

lua提供了API用於在c/c++中構造lua的執行環境,相關介面如下:

//建立lua執行上下文

lua_State*

luaL_newstate(void) ;

//載入lua指令碼檔案

int luaL_loadfile(lua_State *L, const

char *filename);

lua和c/c++的資料互動通過”棧”進行

,操作資料時,首先將資料拷貝到”棧”上,然後獲取資料,棧中的每個資料通過索引值進行定位,索引值為正時表示相對於棧底的偏移索引,索引值為負時表示相對於棧頂的偏移索引,索引值以1或-1為起始值,因此棧頂索引值永遠為-1

,棧底索引值永遠為1 。 “棧”相當於資料在lua和c/c++之間的中轉地。每種資料都有相應的存取介面 。

有興趣一起交流學習c/c++程式設計的夥伴可以加群:941636044一起進步哦!

資料入”棧”介面:

void  (lua_pushnil) (lua_State *L);

void  (lua_pushnumber) (lua_State *L, lua_Number n);

void  (lua_pushinteger) (lua_State *L, lua_Integer n);

void  (lua_pushlstring) (lua_State *L, const char *s, size_t l);

void  (lua_pushstring) (lua_State *L, const char *s);

void  (lua_pushboolean) (lua_State *L, int b);

void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);

資料獲取介面:

lua_Number (lua_tonumber) (lua_State *L, int idx);

lua_Integer (lua_tointeger) (lua_State *L, int idx);

int  (lua_toboolean) (lua_State *L, int idx);

const  char  *(lua_tolstring) (lua_State *L, int idx, size_t *len);

lua_CFunction (lua_tocfunction) (lua_State *L, int idx);

“棧”操作介面:

int (lua_gettop) (lua_State *L);

void (lua_settop) (lua_State *L, int idx);

void (lua_pushvalue) (lua_State *L, int idx);

void (lua_remove) (lua_State *L, int idx);

void (lua_insert) (lua_State *L, int idx);

void (lua_replace) (lua_State *L, int idx);

int (lua_checkstack) (lua_State *L, int sz);

lua中定義的變數和函式存放在一個全域性table中,索引值為LUA_GLOBALSINDEX

,table相關操作介面:

void (lua_gettable) (lua_State *L, int idx);

void (lua_getfield) (lua_State *L, int idx, const char *k);

void (lua_settable) (lua_State *L, int idx);

void (lua_setfield) (lua_State *L, int idx, const char *k);

當”棧”中包含執行指令碼需要的所有要素(函式名和引數)後,呼叫lua_pcall執行指令碼:

int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);

下面進行例項說明:

func.lua

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

//lua標頭檔案

#include <lua.h>

#include <lualib.h>

#include <lauxlib.h>

 

#define err_exit(num,fmt,args)  \

    do{printf("[%s:%d]"fmt"\n",__FILE__,__LINE__,##args);exit(num);} while(0)

#define err_return(num,fmt,args)  \

    do{printf("[%s:%d]"fmt"\n",__FILE__,__LINE__,##args);return(num);} while(0)

 

//lua中呼叫的c函式定義,實現加法

int csum(lua_State* l)

{

    int a = lua_tointeger(l,1) ;

    int b = lua_tointeger(l,2) ;

    lua_pushinteger(l,a+b) ;

    return 1 ;

}

 

int main(int argc,char** argv)

{

    lua_State * l = luaL_newstate() ;        //建立lua執行環境

    if ( l == NULL ) err_return(-1,"luaL_newstat() failed");

    int ret = 0 ;

    ret = luaL_loadfile(l,"func.lua") ;      //載入lua指令碼檔案

    if ( ret != 0 ) err_return(-1,"luaL_loadfile failed") ;

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

    if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ;

 

    lua_getglobal(l,"width");              //獲取lua中定義的變數

    lua_getglobal(l,"height");

    printf("height:%ld width:%ld\n",lua_tointeger(l,-1),lua_tointeger(l,-2)) ;

    lua_pop(l,1) ;                        //恢復lua的棧

 

    int a = 11 ;

    int b = 12 ;

    lua_getglobal(l,"sum");               //呼叫lua中的函式sum

    lua_pushinteger(l,a) ;

    lua_pushinteger(l,b) ;

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

    if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ;

    printf("sum:%d + %d = %ld\n",a,b,lua_tointeger(l,-1)) ;

    lua_pop(l,1) ;

 

    const char str1[] = "hello" ;

    const char str2[] = "world" ;

    lua_getglobal(l,"mystrcat");          //呼叫lua中的函式mystrcat

    lua_pushstring(l,str1) ;

    lua_pushstring(l,str2) ;

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

    if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ;

    printf("mystrcat:%s%s = %s\n",str1,str2,lua_tostring(l,-1)) ;

    lua_pop(l,1) ;

 

    lua_pushcfunction(l,csum) ;         //註冊在lua中使用的c函式

    lua_setglobal(l,"csum") ;           //繫結到lua中的名字csum

 

    lua_getglobal(l,"mysum");           //呼叫lua中的mysum函式,該函式呼叫本程式中定義的csum函式實現加法

    lua_pushinteger(l,a) ;

    lua_pushinteger(l,b) ;

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

    if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ;

    printf("mysum:%d + %d = %ld\n",a,b,lua_tointeger(l,-1)) ;

    lua_pop(l,1) ;

 

    lua_close(l) ;                     //釋放lua執行環境

    return 0 ;

}