当前位置: 首页 > news >正文

#Lua:Lua调用C++生成的DLL库

Lua调用C++生成的DLL库

本文参考了某大佬的博客,写得十分详细,推荐!!!

需求:

在之前的求解器中添加了Lua库,使得程序可以在Lua脚本中实现自定义函数功能,考虑到未来可能需要与第三方程序库进行耦合计算,现在想到可以借助Lua脚本,在脚本中调用第三方动态库,以实现其功能的扩展。接下来将要简要记录下Lua中调用第三方库的实现过程。

编译Lua库

在windows平台下,借助mingw编译器进行编译。

首先需要去下载Lua源代码,这里下载的是最新的 Lua5.4

在安装路径下进行编译,源码中已经写好了Makefile,可以直接进行编译

mingw32-make mingw
mingw32-make install local

在install目录下得到lua.exe,lua54.dll,liblua.a 等可执行文件,动态库与静态库

C++编写DLL接口

以下给出了一个示例,注释比较详细

cpp2dll.cpp

#include <Windows.h>
#include "lua.hpp"
#include <iostream>
#include <time.h>
#include <cmath>

// 函数示例:参数输入顺序
int Lua_printf(lua_State *L)
{
    int n = lua_gettop(L); // 判断输入参数个数
    switch (n)
    {
    case 0:
        std::cout << "intput Para Number is 0" << std::endl;
        break;
    default:
        std::cout << "intput Para is " << n << std::endl;
        int a = 0;
        for (int i = 1; i <= n; ++i)
        {
            a = lua_tonumber(L, i); // 从栈底,向上依次读取数据
            std::cout << a << " ";
        }
        std::cout << std::endl;
        break;
    };
    return n; // 返回n个参数
}

int Lua_pow(lua_State *L)
{
    int n = lua_gettop(L); // 判断输入参数个数
    if (n != 2)
    {
        std::cout << "intput Para Number is not 2" << std::endl;
        return -1;
    }
    double a, b, temp;

    a = lua_tonumber(L, 1);
    b = lua_tonumber(L, 2);

    int re = std::pow(a, b);
    std::cout << "a=" << a << "|b=" << b << "|re=" << re << std::endl;
    // lua_pushstring(L, "re="); // 将返回结果压入栈中
    lua_pushnumber(L, re); // 将返回结果压入栈中
    // return 2;
    return 1;
}

// 注册名称与函数的对应关系
static const luaL_Reg name_and_func[]{
    {"printf", Lua_printf},
    {"pow", Lua_pow},
    {NULL, NULL}};

// 注册函数:函数名称"luaopen_xxx",其中,xxx必须是dll的名称,即"xxx.dll"
extern "C"
{
    int __declspec(dllexport) luaopen_cpp2dll(lua_State *L)
    {
        printf("start luaopen_lib\n");
        luaL_newlib(L, name_and_func); // 创建一个新表,并将函数入栈
        printf("end luaopen_lib\n");
        return 1;
    }
}

编译DLL

编译时需要链接到Lua生成的静态库,所以g++编译时需要指定lua头文件路径,以及静态库路径,编译命令如下

g++ cpp2dll.cpp -O3 -o cpp2dll.dll -shared -fPIC -I ./lua54/include -L absolute/path/to/lua54/lib -llua54

至此生成得Lua可以识别的动态链接库cpp2dll.dll

Lua中调用DLL

编写如下的Lua脚本

test.lua

local cpp2dll = require("cpp2dll")

cpp2dll.printf()
cpp2dll.printf(0,1,2,3)

a=2
b=10
print(a,"^",b,"=",cpp2dll.pow(a,b))
print(b,"^",a,"=",cpp2dll.pow(b,a))

lua.exe 执行test.lua脚本

得到如下输出

cmd$ lua.exe test.lua
start luaopen_lib
end luaopen_lib
intput Para Number is 0
intput Para is 4
0 1 2 3
a=2|b=10|re=1024
2       ^       10      =       1024.0
a=10|b=2|re=100
10      ^       2       =       100.0

最后,在Lua脚本中成功调用C++编写的动态链接库

相关文章:

  • Java线程池七个参数详解
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • VINS学习笔记
  • java毕业设计气候分析平台源码+lw文档+mybatis+系统+mysql数据库+调试
  • 手把手教你微信公众号如何给指定用户发送消息提醒
  • 基于图搜索的规划算法之 A* 家族(八):Theta* 算法
  • 数学建模中常用的十大算法
  • python类的封装,继承和多态
  • Spring MongoDB查询附近的人功能实现
  • 第04篇:Resources资源文件处理,再也不怕找不到文件了。
  • 【微信小程序】页面tab栏与页面内容联动
  • spring 启动了两个tomcat 端口问题分析
  • (四)JPA - JQPL 实现增删改查
  • 焦虑经济衍生冥想生意,年轻人会为“放空”买单吗?
  • linux之framebuffer(1)
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • [nginx文档翻译系列] 控制nginx
  • Apache的基本使用
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • ECMAScript6(0):ES6简明参考手册
  • happypack两次报错的问题
  • React系列之 Redux 架构模式
  • Redis的resp协议
  • Spring声明式事务管理之一:五大属性分析
  • 聚类分析——Kmeans
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 自定义函数
  • #1014 : Trie树
  • #在 README.md 中生成项目目录结构
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (Forward) Music Player: From UI Proposal to Code
  • (Oracle)SQL优化技巧(一):分页查询
  • (WSI分类)WSI分类文献小综述 2024
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (十)c52学习之旅-定时器实验
  • (十五)使用Nexus创建Maven私服
  • (循环依赖问题)学习spring的第九天
  • (译) 函数式 JS #1:简介
  • (转)程序员疫苗:代码注入
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NetCore部署微服务(二)
  • .NET面试题(二)
  • [ 蓝桥杯Web真题 ]-布局切换
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [8481302]博弈论 斯坦福game theory stanford week 1
  • [Angular 基础] - 自定义指令,深入学习 directive
  • [AUTOSAR][诊断管理][ECU][$37] 请求退出传输。终止数据传输的(上传/下载)
  • [BUUCTF 2018]Online Tool(特详解)
  • [Enterprise Library]调用Enterprise Library时出现的错误事件之关闭办法
  • [JS]数据类型
  • [Python GUI PyQt] PyQt5快速入门
  • [RISCV] 为android14添加一个新的riscv device
  • [shell,hive] 在shell脚本中将hiveSQL分离出去