C++,C与Lua相互调用交互实践

原创
2020/07/23 09:15
阅读数 474

C++调Lua

注:使用了Lua5.4 32位的编译器命令行

C程序(使用vs的nuget包管理器安装了lua5.4的依赖)

extern "C" {
	#include <lua.h>
	#include <lauxlib.h>
	#include <lualib.h>
}

int main()
{
	lua_State* L = luaL_newstate();
	luaL_openlibs(L);
	printf("——————开始运行脚本——————\n");
	if (luaL_loadfile(L, "main.lua") || lua_pcall(L, 0, 0, 0) != 0) {
		printf("Lua语法错误:\n%s\n", luaL_checkstring(L, -1));
	}
	printf("——————脚本运行完毕——————\n");
	lua_close(L);
	return 0;
}

Lua脚本内容

print("hello world!")

Lua调C

C程序(使用vs的nuget包管理器安装了lua5.4的依赖)

注:使用VS创建一个dll工程


// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"


#include <stdio.h>
#include <string.h>


extern "C" {
    #include <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
}

//待注册的C函数
//需要说明的是,该函数必须以C的形式被导出,因此extern "C"是必须的。
//定义一个求取平均数的函数
extern "C" int average(lua_State * L)
{
    double sum = 0;
    int num = lua_gettop(L);//获取参数的个数
    for (int i = 1; i <= num; i++)
        sum += lua_tonumber(L, i);
    //依次获取所有参数值,相加
    lua_pushnumber(L, sum / num);//将平均数压如栈,供lua获取

    return 1;//返回返回值个数,通知lua应该在栈里取几个值作为返回结果
}


extern "C" int Communicate(lua_State * L)
{
    const char* name = lua_tostring(L, 1);//获取字符串
    printf("Hello %s\n", name);
    printf("I`m in C,I send a message to you");
    lua_pushstring(L, "This message from C");
    return 1;
}
//luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字。
//第一个字段为C函数指针。
//结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。
static luaL_Reg cMethods[] = {
    { "average", average },
    { "Communicate", Communicate },
    { NULL, NULL }
};

//该C库的唯一入口函数。其函数签名等同于上面的注册函数。见如下几点说明:
//1. 我们可以将该函数简单的理解为模块的工厂函数。
//2. 其函数名必须为luaopen_xxx,其中xxx表示library名称。Lua代码require "xxx"需要与之对应。
//3. 在luaL_register的调用中,其第一个字符串参数为模块名"xxx",第二个参数为待注册函数的数组。
//4. 需要强调的是,所有需要用到"xxx"的代码,不论C还是Lua,都必须保持一致,这是Lua的约定,
//   否则将无法调用。
extern "C" __declspec(dllexport)
int luaopen_Mydll(lua_State * L)
{
    const char* libName = "Mydll";
#ifdef lua5.1
    //5.1 下直接使用luaL_register 就好
    luaL_register(L, libName, cMethods);
#else //lua5.2
    lua_newtable(L);
    //先把一个table压入VS,然后在调用luaL_setfuncs就会把所以的func存到table中
    //注意不像luaL_register这个table是个无名table,可以在的使用只用一个变量来存入这个table。
    //e.g local clib = require "libname". 这样就不会污染全局环境。比luaL_register更好。
    luaL_setfuncs(L, cMethods, 0);
#endif
   
    return 1; //返回table
}

lua脚本

local Mydll = require "Mydll" --引入包 --在调用时,必须是package.function print(Mydll.average(1.0,2.0,3.0,4)); print(Mydll.Communicate("Zack"));

参考资料

  1. https://blog.csdn.net/qq_35807952/article/details/79912769
  2. https://www.bookstack.cn/read/luaprimer/08.md
  3. https://blog.csdn.net/tianxiawuzhei/article/details/46334457
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部