lua调用c详解Windows版,以及一些踩过的坑

新将项目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;
	}
}

参考:
lua调用c详解(Windows版+Linux版)

Lua教程(二十):Lua调用C函数

vs2017编译Lua最新源码,生成动态链接库版本

lua require绝对路径文件时 module not found解决方法

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值