新将项目mylib
添加main.c文件,设置工程为Release x64版
在设置中添加lua的头文件目录:
添加lua.lib
方式一:
或者采用方式二添加lua.lib
#pragma comment(lib,"D:\\Program Files\\lua-5.3.5\\build\\lua.lib")
本文采用方式一
继续设置:
main.c源码:
#include <stdio.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
static int add(lua_State* L)
{
double op1 = luaL_checknumber(L, 1);//去栈中拿参数
double op2 = luaL_checknumber(L, 2);
lua_pushnumber(L, op1 + op2);//把结果入栈
return 1;//返回值的个数
}
static int sub(lua_State* L)
{
double op1 = luaL_checknumber(L, 1);
double op2 = luaL_checknumber(L, 2);
lua_pushnumber(L, op1 - op2);
return 1;
}
static luaL_Reg mylibs[] =
{
{"add", add},
{"sub", sub},
{NULL, NULL}
};
__declspec(dllexport)//这个很重要,设置这个函数为外部链接 Linux不需要
int luaopen_mylib(lua_State* L) //函数名很重要,luaopen_xxx,lua脚本require(“xxx”)和xxx.dll、xxx.so,这4个一定要这样,
{
luaL_newlib(L, mylibs);
return 1;
}
编译:
遇到的坑一:
新建的时候没有注意,添加的是main.cpp文件:
这时候有两种解决方法,一是将main.cpp改成main.c;
方法二是将lua的头文件都用extern "C"包裹起来,然后重新编译
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
测试,将生成的mylib.dll复制到lua.exe目录中(这里为了方便测试,后面可以设置package.path路径)
,然后在这个目录下添加一个test.lua文件:
local my_math = require("mylib")
print(my_math.add(1, 2))
print(my_math.sub(1, 2))
在这过程中,你可能还会遇到我之前遇到的坑:
坑一:
报错"multiple lua vms detected".
主程序编译时引用的lua静态库.编译功能模块的动态链接库时也引用的lua 静态库.
主程序运行lua代码,lua代码中需要加载功能模块库,这个时候lua加载模块失败,报错"multiple lua vms detected".
原因:加载两次lua静态库,创建了两个虚拟机,导致冲突.
解决办法:主程序和模块库都改成引用lua的动态库,加载多次动态库共享一份,不会冲突.
解决方法就按照我之前写的编译过程,重新编译lua.lib,lua.dll,lua.exe
vs2017编译Lua最新源码,生成动态链接库版本
坑二:
这时候有几个地方要检查。
int luaopen_mylib(lua_State* L)
这里的luaopen_mylib,这里的mylib是require的时候加载的模块名,mylib.dll也要叫这个名。
最防不胜防的另外一种情况,就是你用的main.cpp,源文件中
这里还要再用extern "C"包裹一下,这样才能被lua识别。
如果你用的是main.c这样的文件,什么都不用加,恭喜你成功避免了这一个坑,但是如果你加的是main.cpp,则需要将lua头文件用extern "C"包裹,还需要将luaopen_xx也用extern "C"包裹起来
废话不多说,main.cpp文件为:
#include <stdio.h>
#include <string.h>
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
static int add(lua_State* L)
{
double op1 = luaL_checknumber(L, 1);//去栈中拿参数
double op2 = luaL_checknumber(L, 2);
lua_pushnumber(L, op1 + op2);//把结果入栈
return 1;//返回值的个数
}
static int sub(lua_State* L)
{
double op1 = luaL_checknumber(L, 1);
double op2 = luaL_checknumber(L, 2);
lua_pushnumber(L, op1 - op2);
return 1;
}
static luaL_Reg mylibs[] =
{
{"add", add},
{"sub", sub},
{NULL, NULL}
};
extern "C"
{
__declspec(dllexport)//这个很重要,设置这个函数为外部链接 Linux不需要
int luaopen_mylib(lua_State* L) //函数名很重要,luaopen_xxx,lua脚本require(“xxx”)和xxx.dll、xxx.so,这4个一定要这样,
{
luaL_newlib(L, mylibs);
return 1;
}
}