在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