在lua中调用 C模块(以及 multiple Lua VMs detected 错误的解决)

在lua中有两种调用c的方式,一种是c作为主程序,向lua中注册函数,然后调用,另一种是把c编写成dll模块,在lua中调用,

//==============割============

先来第二种,在lua脚本中调用c模块:(这种方式可是折腾了本人很久)

先贴代码:

#include <stdio.h>
#include <lua.hpp>

//这里要用动态库,不能用静态库(后面解释)
#ifndef _DEBUG
#pragma comment(lib,"Share-5.3.lib")
#else
#pragma comment(lib,"Share-5.3_d.lib")
#endif // !_DEBUG

#define C_COMPILE extern "C"
#define DLL_EXOPRT  extern "C" __declspec(dllexport)


C_COMPILE static int add(lua_State* L)
{
	double op1 = luaL_checknumber(L, 1);
	double op2 = luaL_checknumber(L, 2);
	const char* szTmp = luaL_checkstring(L, 3);

	printf("arg - 3: %s\n", szTmp);

	lua_pushnumber(L, op1 + op2);

	return 1;  //返回参数的个数
}

//luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字,第二个字段为C函数指针。
//结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。
C_COMPILE static luaL_Reg myLibs[] =
{
	{ "add", add },
	{ NULL, NULL }
};

//注意这个函数名, luaopen_XXX,  XXX就是你生成的dll的名字,在lua加载这个dll模块时,会调用这个函数。
DLL_EXOPRT int luaopen_luaCallDll(lua_State* L)  
{
        //luaL_openlib(L, "mylib", mylib, 0); //lua5.1使用的这种方式,lua5.2开始已经不能用了 

        luaL_newlib(L, myLibs); //lua5.3,也可以用下面这种方式,这个函数其实就是下面这种方式的宏定义
       //lua_newtable(L);
      //luaL_setfuncs(L, myLibs,0);

	return 1;
}

 

//lua脚本

local cdll = require"luaCallDll";
print("result:",cdll.add(5,6,"str Test"));

这段脚本要跑起来却是让我折腾了蛮久。

首先第一个问题,由于人穷,用不起LuaStudio,所以只有用免费的LuaEditor,但是这个只支持lua5.1,这段脚本LuaEditor编译不过,  本人又是比较用新东西的,所以只好自己编译Lua解释器了,从这个git库可以拿到lua5.3的vs2013工程(https://git.oschina.net/liLinux/lua-5.3.git),已经做好配置,直接编译出lua动态库,静态库和lua的解释器,编译器。

lua解析器和编译器运行的效果,怎么用可以查看lua的手册  (http://www.runoob.com/manual/lua53doc/manual.html  中文翻译版的手册,当然也可以看官方的英文版)

lua解释器:

lua编译器,需要带参数使用




编译lua解释器的时候要依赖于lua动态库来编译,不能编译成静态的,否则在调用c模块的时候就会出现 multiple Lua VMs detected 的错误


上面的lua脚本正常运行的结果。。


//==============在次割============

//下面来说下主要的问题,为什么c和lua解析器都要用动态编译

现在看下错误  multiple Lua VMs detected ,什么意思呢,就是说有多个虚拟机加载,起冲突了。

也就是说只能加载一个lua虚拟机。

那么如果lua解释器用静态来编译,就会加载一个虚拟机,当解释器去调用c模块时,c模块在编译的时候是需要 conmmit 静态或者动态的lua库的,那么这时候也会加载一个lua虚拟机,所以自然就起了冲突,怎么办呢,其实很简单,只要lua解释器和c库都调用同一个dll就好,dll是共享库,只会加载一次到内存,所以就不会出现冲突。

所以,保证编写的c模块和lua解释器是依赖于同一个Lua的共享库就好。


================华丽丽的分割线================

第一种,以c做为主程序:

直接上代码,代码中解释

#include "stdafx.h"
#include <string.h>
#include <lua.hpp>
#include <stdlib.h>

#ifndef _DEBUG
#pragma comment(lib,"Static-5.3.lib")
#else
#pragma comment(lib,"Static-5.3_d.lib")
#endif // !_DEBUG
//====

 //待Lua调用的c注册函数
static int add2Lua(lua_State* L)  //需要注意:注册到lua中的c函数一定要是  int (*func)(lua_State*)  这样类型的
{
	//检查栈中的参数是否合法,1表示Lua调用时的第一个参数(从左到右),依此类推。
	//如果Lua代码在调用时传递的参数不为number,该函数将报错并终止程序的执行。
	double op1 = luaL_checknumber(L, 1);
	double op2 = luaL_checknumber(L, 2);
	//将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
	lua_pushnumber(L, op1 + op2);
	//返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
	return 1;
}

//另一个待Lua调用的C注册函数。
static int sub2Lua(lua_State* L)
{
	double op1 = luaL_checknumber(L, 1);
	double op2 = luaL_checknumber(L, 2);
	lua_pushnumber(L, op1 - op2);
	return 1;
}

//这句是待会注册了c函数之后要执行的 lua脚本
const char* testfunc = "print(add2Lua(1.0,2.0)); print(sub2Lua(20.1,19))";

void Test()
{
	lua_State* L = luaL_newstate();  //创建一个lua虚拟机
	luaL_openlibs(L);
	//将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为注册到Lua中函数名,第二个参数为实际C函数的指针。
	lua_register(L, "add2Lua", add2Lua);
	lua_register(L, "sub2Lua", sub2Lua);
	//在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。
	if (luaL_dostring(L, testfunc))   //加载并运行指定的(testfunc)字符串
		printf("Failed to invoke.\n");
	lua_close(L);
}

int _tmain(int argc, _TCHAR* argv[])
{
	Test();

	system("pause");
	return 0;
}


如何在C/C++中调用lua:可以查看本人的这篇Blog: 

http://blog.csdn.net/qq_30949367/article/details/51348322


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值