上周看了一下lua的package和OO,感覺不錯, lua並不像python程式員抨擊的那樣不優美.
順便看了一下pil中, c函數調用lua以及lua調用c函數的內容.
一、c調用lua函數一般的過程是:
1. load一個lua的檔案,形成一個閉包並執行它
2. 在棧中壓入函數的名稱
3. 依次在棧中壓入函數的實參
4. 使用lua_pcall調用lua函數。 形式是: lua_pcall(L, 參數個數,結果個數, 錯誤處理函數在棧中的索引)
此時此函數相關的棧已經被清空。執行lua完畢後,如果成功,結果依次將壓入棧中, 如果不成功,錯誤資訊將 壓入棧中
5. 從棧中讀取返回結果或者錯誤資訊。
下面是一則執行個體:
--[[
func.lua
--]]
function f(x, y)
return (x^2 * math.sin(y))/(1 - x)
end
/**
* main.cpp
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
void error (lua_State *L, const char *fmt, ...)
{
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
lua_close(L);
exit(EXIT_FAILURE);
}
int main (void)
{
lua_State *L = luaL_newstate();
lua_cpcall(L, luaopen_base, 0);
lua_cpcall(L, luaopen_io, 0);
lua_cpcall(L, luaopen_math, 0);
lua_cpcall(L, luaopen_string, 0);
// 載入func.lua,並運行
if (luaL_loadfile(L, "func.lua") || lua_pcall(L, 0, 0, 0))
error(L, "cannot run configuration file: %s", lua_tostring(L, -1));
double x, y;
printf("請輸入一個數字:");
scanf("%d", &x);
printf("%d/n", x);
printf("再輸入一個數字:");
scanf("%d", &y);
printf("%d/n", y);
lua_getglobal(L, "f");
lua_pushnumber(L, x);
lua_pushnumber(L, y);
if (lua_pcall(L, 2, 1, 0) != 0)
error(L, "error running function `f': %s", lua_tostring(L, -1));
if (!lua_isnumber(L, -1))
error(L, "function `f' must return a number");
double z = lua_tonumber(L, -1);
lua_pop(L, 1); /* pop returned value */
printf("結果是: /t %d' /n", z);
lua_close(L);
}
二、lua調用c函數(寫成庫的例子)
lua調用庫在windows下是dll檔案,在unix/linux下面是so檔案
vs的過程如下:
1. 建立一個dll的工程
2. 定義一個def檔案,定義dll的匯出,我的mylib.def定義如下:
LIBRARY mylib.dll
DESCRIPTION "aol's first dll for lua"
EXPORTS
luaopen_mylib
3. 編寫庫,建立一個cpp檔案.
4. 定義庫函數,這裡以pil的lsin函數,輸出傳入參數的sin()值
5. 定義luaL_reg數組,這個是註冊一系列公開給lua調用的函數數組. 數組最後一個元素必須是 {NULL, NULL} 的luaL_reg結構用來做結束標識.
6. 用luaL_openlib聲明主函數
執行個體如下:
/*
* main.cpp
*/
#include <math.h>
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
static int l_sin (lua_State *L)
{
double d = luaL_checknumber(L, 1);
lua_pushnumber(L, sin(d));
return 1; /* number of results */
}
static const struct luaL_reg mylib [] = {
{"lsin", l_sin},
{NULL, NULL} /* sentinel */
};
int luaopen_mylib (lua_State *L)
{
luaL_openlib(L, "mylib", mylib, 0);
return 1;
}
產生mylib.dll之後把檔案拷入lua的安裝根目錄就可以調用了.
運行lua,進入lua環境,調用如下(lua版本5.1):
> package.loadlib("mylib.dll", "luaopen_mylib")()
> print(mylib.lsin(10))
-0.54402111088937
>