本文环境为windows10+visual studio 2013
lua在linux下编译、添加cc++模块还是比较直接方便的,资料也多,windows就那么直接了,经过一番折腾终于成功了编译源码
首先去下载最新的源码,解压
打开vs的命令行工具,如图,若要64位编译打开x64工具进入解压的源码目录抛开本身链接的运行时库类型(MD、 MT),编译可分两种,链接静态库或动态库编译链接静态lib,最终生成lua.exe(解释器)、luac.exe(编译器)、lua.lib(静态链接库)静态链接的lua.exe不依赖dll,但是无法添加新的c\c++模块,因为相关函数不能link多份,只想把lua作为程序嵌入脚本或者运行纯lua静态链接更便捷cl /MD /O2 /c *.cren lua.obj lua.oren luac.obj luac.olib /OUT:lua.lib *.objlink /OUT:lua.exe lua.o lua.liblink /OUT:luac.exe luac.o lua.lib1、各个c文件编译成obj文件2,3、 lua.obj、luac.obj含有main函数,生成lib或dll时要排除4、合并obj生成lib库,包含所有obj的函数5、lua.o中有main函数,链接lua.lib生成lua.exe6、luac.o中有main函数,链接lua.lib生成luac.exe编译链接动态dll,最终生成lua.exe(解释器)、luac.exe(编译器)、lua.dll(静态链接库)、lua.lib(导出库)动态链接的lua.exe依赖dll,后续可添加新的dll模块cl /MD /O2 /c /DLUA_BUILD_AS_DLL *.cren lua.obj lua.oren luac.obj luac.olink /DLL /IMPLIB:lua.lib /OUT:lua.dll *.obj link /OUT:lua.exe lua.o lua.liblink /OUT:luac.exe luac.o *.obj1:在cl编译的时候加入了一个自定义的宏 /DLUA_BUILD_AS_DLL 这是因为在luaconf.h文件中定义了LUA_BUILD_AS_DLL宏:#if defined(LUA_BUILD_AS_DLL) /* { */#if defined(LUA_CORE) || defined(LUA_LIB) /* { */#define LUA_API __declspec(dllexport)#else /* }{ */#define LUA_API __declspec(dllimport)#endif /* } */#else /* }{ */#define LUA_API extern#endif 它控制了__declspec(dllexport)和__declspec(dllimport)的定义,必须加上这个开关才有这两个定义,否则编译出来的DLL没有任何导出函数。luac.c中定义了LUA_CORE,最后不要链接动态库2、3:重命名编译成的lua.obj luac.obj 在生成dll库时不需要这两文件(含有main函数),否则在链接生成最终的exe文件时会有函数重定义的错误。4:链接1步中编译出的obj文件,生成lua.dll和导出库lua.lib,如果没有定义DLUA_BUILD_AS_DLL 宏,不会生成导出库lua.lib,无法进行最后的链接,lua.lib中只有声明导出的函数(LUA_API),所以链接生成luac.exe时要链接*.obj文件。5:链接1步中编译出的lua.obj文件(lua.o),和4步中生成的导出库,生成lua.exe(必须有lua.dll才能运行)。6:链接luac.o,不能链接llua.lib导出库(只有导出函数,有些函数找不到),重新链接所有的obj,运行不依赖lua.dll,因为*.obj是__declspec(dllexport)编译生成,链接还会生成luac.lib导出库,应该和lua.lib是一样的
也可以在vs建立相关项目,将全部源码文件添加,根据需要排除或添加lua.cluac.c,配置相关属性进行编译
编译脚本
两种编译方式写了bat脚本(同样要在vs的命令行工具中运行),放到解压目录,会将编译结果以及头文件拷贝到相应目录
build_dll.bat:
@echo offrem out lua.exe luac.exe lua.lib lua.dllset ver=5.3.0set op=build_dllmd %op%md %op%\include\cd srccl /MD /O2 /c /DLUA_BUILD_AS_DLL *.cren lua.obj lua.oren luac.obj luac.olink /DLL /IMPLIB:lua.lib /OUT:lua.dll *.obj link /OUT:lua.exe lua.o lua.liblink /OUT:luac.exe luac.o *.objmove *.exe ..\%op%\move *.lib ..\%op%\move *.dll ..\%op%\del /q *.objdel /q *.odel /q *.expcopy lua.h ..\%op%\include\copy lualib.h ..\%op%\include\copy lauxlib.h ..\%op%\include\copy lua.hpp ..\%op%\include\copy luaconf.h ..\%op%\include\cd ..\
build_static.bat:
@echo offset ver=5.3.0set op=build_staticrem out lua.exe luac.exe lua.lib md %op%md %op%\include\cd srccl /MD /O2 /c *.cren lua.obj lua.oren luac.obj luac.olib /OUT:lua.lib *.objlink /OUT:lua.exe lua.o lua.liblink /OUT:luac.exe luac.o lua.libmove *.exe ..\%op%\move *.lib ..\%op%\move *.dll ..\%op%\del /q *.objdel /q *.odel /q *.expcopy lua.h ..\%op%\include\copy lualib.h ..\%op%\include\copy lauxlib.h ..\%op%\include\copy lua.hpp ..\%op%\include\copy luaconf.h ..\%op%\include\cd ..\
编写cc++模块
1.在vs中建立c++项目dlltest,属性->常规->配置类型,选择动态库dll,
2.如果是拷贝所有lua源码去除lua.c、luac.c添加到项目,需要在属性->C/C++->预处理器中,添加宏定义LUA_BUILD_AS_DLL,如果已有编译成的导入库lua.lib和lua.dll,不用定义LUA_BUILD_AS_DLL宏,导出库中本就是导出函数拷贝头文件与lua.lib配置属性->C/C++->常规->附加包含目录 和 配置属性->链接器->常规->附加库目录或者直接在代码中写 #pragma comment(lib, "路径")3.添加源文件dlltest.cpp#include "../build_dll/include/lua.hpp"#pragma comment(lib, "../build_dll/lua.lib")#define EXTERN_C extern "C"#define API_DECLSPEC __declspec(dllexport)EXTERN_C static int l_mystr(lua_State *L){ lua_pushstring(L, "looyer");//返回的第一个参数, 字符串“looyer” lua_pushnumber(L, 37);//返回的第二个参数,数字37 //返回第三个参数table = {['ac'] = 17, [2] = "bn"} lua_newtable(L);//在栈顶创建一个table //方法一,设置table的键和值 lua_pushstring(L, "ac"); lua_pushnumber(L, 17); lua_settable(L, -3);//在table中设置键值对['ac'] = 17, 设置后,自动pop掉栈顶的两个元素 //方法二,设置table的键和值 lua_pushstring(L, "bn"); lua_setfield(L, -2, "2");//将栈顶元素设置为键“2”的值,并且赋个索引为-2的栈中table return 3;//返回参数的个数 }//演示输入多个参数,检查输入一个数字,一个字符串,一个table EXTERN_C static int l_myadd(lua_State *L){ int a = luaL_checknumber(L, 1); const char *p = luaL_checkstring(L, 2); lua_getfield(L, 3, "yt");//将第三个参数table的“yt”键的值压入栈 int b = luaL_checknumber(L, -1);//取出该“yt”键的值 lua_pushnumber(L, a + b); return 1;//返回一个参数 }//只有luaopen_dlltest需要dllexport//_后要和生成的dll同名否则require找不到对应的库EXTERN_C API_DECLSPEC int luaopen_dlltest(lua_State *L){ luaL_Reg l[] = { { "mystr", l_mystr }, { "myadd", l_myadd }, { NULL, NULL }, }; luaL_newlib(L, l); return 1;}
生成,在Release或Debug目录下拷贝dlltest.dll到运行目录
在运行目录编写mytest.lua
dlltest = require "dlltest"local cpath = package.cpath..";"print("-----------start-------------")for path in string.gmatch(cpath, "(.-);") do print(path)enda, b, c = dlltest.mystr()print(a,b,c)print(c[ac], c[2])print(c["ac"], c[2])print(c["ac"], c["2"])a = 10b = "tty"c = { ["yt"] = 19}print(dlltest.myadd(a,b, c))print("-----------end-------------")
在运行目录打开命令行,用lua.exe 运行mytest.lua