以下内容取自网上公开文档
1.下载源码:http://www.lua.org/ftp/
2.编译dll,lib和exe:
2.1在“C/C++” -> “预处理器” -> “预处理器定义” 中添加LUA_BUILD_AS_DLL:不加没有lib
2.2不添加(lua.c 和 luac.c)
2.3编译exe添加对应的文件
lua.c:编译器
luac.c:解释器
3.使用生成的库(x64,x86要一致)
3.1栈的操作
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 //注意添加extern "C",否则出现链接错误 5 extern "C" { 6 #include "lua.h" 7 #include "lualib.h" 8 #include "lauxlib.h" 9 } 10 11 #ifdef _DEBUG 12 #pragma comment(lib,"./Lua/Debug/Luad.lib") 13 #else 14 #pragma comment(lib,"./Lua/Release/Lua.lib") 15 #endif 16 17 static void stackDump(lua_State* L) 18 { 19 int i = 0; 20 int top = lua_gettop(L); 21 for (i = 1; i <= top; i++) 22 { 23 int t = lua_type(L, i); 24 switch (t) 25 { 26 case LUA_TSTRING: /* strings */ 27 printf("`%s'", lua_tostring(L, i)); 28 break; 29 case LUA_TBOOLEAN: /* booleans */ 30 printf(lua_toboolean(L, i) ? "true" : "false"); 31 break; 32 case LUA_TNUMBER: /* numbers */ 33 printf("%g", lua_tonumber(L, i)); 34 break; 35 default: /* other values */ 36 printf("%s", lua_typename(L, t)); 37 break; 38 } 39 printf(" "); /* put a separator */ 40 } 41 printf("\n"); /* end the listing */ 42 } 43 44 int main(int argc, char** argv) 45 { 46 lua_State* L = luaL_newstate(); // 创建Lua虚拟机 47 48 luaL_openlibs(L); // 打开Lua状态机"L"中的所有Lua标准库 49 50 // 向虚拟栈中压入值 51 lua_pushboolean(L, 1); // true 52 lua_pushnumber(L, 10); // 10 53 lua_pushnil(L); // nil 54 lua_pushstring(L, "hello"); // "hello" 55 stackDump(L); // true 10 nil 'hello' 56 57 lua_pushvalue(L, -4); // 将索引-4处的值的副本入栈 58 stackDump(L); // true 10 nil 'hello' true 59 60 lua_replace(L, 3); // 将栈顶元素移动到索引3处,并覆盖原先的元素 61 stackDump(L); // true 10 true 'hello' 62 63 lua_settop(L, 6); // 将栈顶设置为索引6处,多出来的新元素被赋值为"nil" 64 stackDump(L); // true 10 true 'hello' nil nil 65 66 lua_remove(L, -3); // 移除索引-3处的元素,其上所有元素下移 67 stackDump(L); // true 10 true nil nil 68 69 lua_settop(L, -5); // 将栈顶设置为索引-5处 70 stackDump(L); // true 71 72 lua_close(L); // 关闭Lua状态机 73 74 system("pause");//在Linux下编译,请注释调这行 75 76 return 0; 77 }View Code
3.2 C调用Lua
1 static int multi_math(lua_State* L, int x, int y) 2 { 3 int ret = 0; 4 int add_ret = 0; 5 int sub_ret = 0; 6 int mul_ret = 0; 7 8 //call lua_add 9 lua_getglobal(L, "lua_add");//把函数lua_add压入栈中 10 stackDump(L); //function 11 lua_pushnumber(L, x); //function 2 12 lua_pushnumber(L, y); //fucntion 2 1 13 stackDump(L); 14 lua_call(L, 2, 1); //指明有2个参数,1个返回值,且把function 2 1弹出栈,并把返回值压入栈 15 16 stackDump(L); 17 add_ret = (int)lua_tonumber(L, -1); 18 stackDump(L); 19 printf("add_ret = %d\n", add_ret); 20 lua_pop(L, 1); //弹出栈顶 21 stackDump(L); 22 23 #if 0 24 //call local lua_sub will cause running error 25 lua_getglobal(L, "lua_sub"); 26 lua_pushnumber(L, x); 27 lua_pushnumber(L, y); 28 lua_call(L, 2, 1); 29 sub_ret = (int)lua_tonumber(L, -1); 30 printf("sub_ret = %d\n", sub_ret); 31 lua_pop(L, 1); 32 #endif 33 //call lua_mul 34 lua_getglobal(L, "lua_mul"); 35 lua_pushnumber(L, x); 36 lua_pushnumber(L, y); 37 lua_call(L, 2, 1); 38 mul_ret = (int)lua_tonumber(L, -1); 39 printf("mul_ret = %d\n", mul_ret); 40 lua_pop(L, 1); 41 42 return ret; 43 } 44 int main(int argc, char** argv) 45 { 46 lua_State* L = luaL_newstate(); // 创建Lua虚拟机 47 luaL_openlibs(L); // 打开Lua状态机"L"中的所有Lua标准库 48 49 printf("call lua ....\n"); 50 if (luaL_dofile(L, "main.lua"))//加载运行main.lua 51 { 52 printf("call lua failed!\n"); 53 } 54 if (multi_math(L, 2, 1)) 55 { 56 printf("call multi_math failed!\n"); 57 } 58 59 lua_close(L); // 关闭Lua状态机 60 61 system("pause"); 62 63 return 0; 64 }View Code
3.3 lua 调用 C
其接口必须遵循Lua要求的形式,即typedef int (*lua_CFunction)(lua_State* L)
1 //待Lua调用的C注册函数。 2 static int add2(lua_State* L) 3 { 4 //检查栈中的参数是否合法,1表示Lua调用时的第一个参数(从左到右),依此类推。 5 //如果Lua代码在调用时传递的参数不为number,该函数将报错并终止程序的执行。 6 double op1 = luaL_checknumber(L, 1); 7 double op2 = luaL_checknumber(L, 2); 8 //将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。 9 lua_pushnumber(L, op1 + op2); 10 //返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。 11 return 1; 12 } 13 //另一个待Lua调用的C注册函数。 14 static int sub2(lua_State* L) 15 { 16 double op1 = luaL_checknumber(L, 1); 17 double op2 = luaL_checknumber(L, 2); 18 lua_pushnumber(L, op1 - op2); 19 return 1; 20 } 21 const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))"; 22 23 int main() 24 { 25 lua_State* L = luaL_newstate(); 26 luaL_openlibs(L); 27 //将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为Lua代码 28 //在调用C函数时使用的全局函数名,第二个参数为实际C函数的指针。 29 lua_register(L, "add2", add2); 30 lua_register(L, "sub2", sub2); 31 //在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。 32 if (luaL_dostring(L, testfunc)) 33 printf("Failed to invoke.\n"); 34 lua_close(L); 35 return 0; 36 37 }View Code
3.4 C函数库成为Lua的模块(暂时不用直接摘录)。
将包含C函数的代码生成库文件,如Linux的so,或Windows的DLL,同时拷贝到Lua代码所在的当前目录,或者是LUA_CPATH环境变量所指向的目录,以便于Lua解析器可以正确定位到他们。在我当前的Windows系统中,我将其copy到"C:\Program Files\Lua\5.1\clibs\",这里包含了所有Lua可调用的C库。见如下C语言代码和关键性注释:
#include <stdio.h>
#include <string.h>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>
//待注册的C函数,该函数的声明形式在上面的例子中已经给出。
//需要说明的是,该函数必须以C的形式被导出,因此extern "C"是必须的。
//函数代码和上例相同,这里不再赘述。
extern "C" int add(lua_State* L)
{
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
lua_pushnumber(L,op1 + op2);
return 1;
}
extern "C" int sub(lua_State* L)
{
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
lua_pushnumber(L,op1 - op2);
return 1;
}
//luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字。
//第一个字段为C函数指针。
//结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。
static luaL_Reg mylibs[] = {
{"add", add},
{"sub", sub},
{NULL, NULL}
};
//该C库的唯一入口函数。其函数签名等同于上面的注册函数。见如下几点说明:
//1. 我们可以将该函数简单的理解为模块的工厂函数。
//2. 其函数名必须为luaopen_xxx,其中xxx表示library名称。Lua代码require "xxx"需要与之对应。
//3. 在luaL_register的调用中,其第一个字符串参数为模块名"xxx",第二个参数为待注册函数的数组。
//4. 需要强调的是,所有需要用到"xxx"的代码,不论C还是Lua,都必须保持一致,这是Lua的约定,
// 否则将无法调用。
extern "C" __declspec(dllexport)
int luaopen_mytestlib(lua_State* L)
{
const char* libName = "mytestlib";
luaL_register(L,libName,mylibs);
return 1;
}
见如下Lua代码:
require "mytestlib" --指定包名称
--在调用时,必须是package.function
print(mytestlib.add(1.0,2.0))
print(mytestlib.sub(20.1,19))