1. 程式人生 > >Lua 與C/C++ 互動系列:通過C呼叫Lua函式(1)

Lua 與C/C++ 互動系列:通過C呼叫Lua函式(1)

1、Lua通過ANSI C 進行編寫,Lua與C互動要遵循一定的協議規則。在Lua 5.1 Reference Manual中明確規定如何通過C Code呼叫Lua 編寫的函式。

     C  code可以呼叫Lua Code編寫的任何函式.本文主要以全域性函式來做演示。

2、首先把C語言呼叫Lua 函式的協議規則說明。Lua 5.1 Reference Manual 中關於void lua_call (lua_State *L, int nargs, int nresults); 函式的描述中詳細說明了協議規則。

void lua_call (lua_State *L, int nargs, int nresults);

To call a function you must use the following protocol:

first, the function to be called is pushed onto the stack;

then, the arguments to the function are pushed in direct order;

that is, the first argument is pushed first.

Finally you call lua_call;

nargs is the number of arguments that you pushed onto the stack.

All arguments and the function value are popped from the stack when the function is called.

The function results are pushed onto the stack when the function returns.

The number of results is adjusted to nresults, unless nresults is LUA_MULTRET.

 In this case, all results from the function are pushed. Lua takes care that the returned values fit into the stack space.
The function results are pushed onto the stack in direct order (the first result is pushed first), so that after the call the last result is on the top of the stack.

呼叫Lua函式必須使用如下協議:1、把函式名稱壓入到虛擬棧。2,從左到右依次把引數壓入到虛擬棧3,呼叫lua_call()函式。

在lua_call()函式中,nargs指定Lua Code函式的引數數量,nresults指定當Lua Code函式呼叫完成後向虛擬棧上面壓入返回結果的數量。

3、在C code中呼叫Lua Code全域性函式

sample_1.cpp檔案

#include <iostream>
using namespace std;
extern "C" 
{
	#include "lua.h"
	#include "lauxlib.h"
	#include "lualib.h"
}
//為了方便說明,在C code中呼叫Lua Code函式,函式以calllua_XXX命名
int  calllua_sum(lua_State *L,int a, int b)
{
	//把_G["name"] 函式壓入到虛擬棧上面
	lua_getglobal(L,"sum");
	//按時Lua函式順序,從左到右依次壓入引數
	lua_pushnumber(L,a);
	lua_pushnumber(L,b);
	//呼叫lua_call()函式,實際呼叫Lua Code函式
	lua_call(L,2,1);
	//當Lua Code函式呼叫結束後,把結果值壓入虛擬棧中
    int sum=(int)lua_tonumber(L,-1);
	return sum;
}
int main(int argc, char **argv)
{         //建立lua_State
	  lua_State *L = lua_open();  /* create state */
	  //註冊標準庫
	  luaL_openlibs (L);
	  //執行sample_1.lua
	  luaL_dofile (L, "sample_1.lua");
	  //呼叫Lua Code函式
	  int sum =calllua_sum(L,1, 2);
	  cout<<"sum:"<<sum<<endl;
	  //關閉lua_State
	  lua_close(L);
           return 1;
}

sample_1.lua 檔案

print("example_1.lua")
--定義全域性變數  sum函式
function sum(a,b)
  return a+b
end


4、在C code中呼叫Lua Code中任何函式。以Table中Field函式為例子

int  calllua_fieldsum(lua_State *L,int a, int b)
{
	//把_G["luaTable"] Table資料結構壓入到虛擬棧上面
	lua_getglobal(L,"luaTable");
	//把luaTable["fieldsum"]函式壓入到虛擬棧上面
	lua_getfield(L,-1,"fieldsum");
	//把_G["luaTable"]從虛擬棧中移除
	lua_remove(L,-2);
	//按時Lua函式順序,從左到右依次壓入引數
	lua_pushnumber(L,a);
	lua_pushnumber(L,b);
	//呼叫lua_call()函式,實際呼叫Lua Code函式
	lua_call(L,2,1);
	//當Lua Code函式呼叫結束後,把結果值壓入虛擬棧中
       int sum=(int)lua_tonumber(L,-1);
	return sum;
}

--定義一個全域性Table
luaTable={}
--在Table欄位中定義函式
luaTable["fieldsum"]=function(a,b) return a+b end

在Lua與C/C++語言互動時,通過C呼叫Lua Code函式是最簡單的一種。因為Lua  C API 為了C語言而設計,C++又包含C語言,所以在呼叫Lua Code函式時原理都一直。

不過C++,提供了在編譯時的模板機制,可以更大的靈活性。同時在lua_pushXXX()函式中,僅僅提供幾種基本的資料型別,這個可以自己擴充套件。