Lua与C++交互

news2024/11/17 1:46:59

文章目录

  • 1、Lua和C++交互
  • 2、基础练习
    • 2.1、加载Lua脚本并传递参数
    • 2.2、加载脚本到stable(包)
    • 2.3、Lua调用c语言接口
    • 2.4、Lua实现面向对象
    • 2.5、向脚本中注册c++的类

1、Lua和C++交互

1、lua和c++交互机制是基于一个虚拟栈,C++和lua之间的所有数据交互都通过这个虚拟栈来完成,无论何时C++想从lua中调用一个值,被请求的值将会被压入栈,C++想要传递一个值给Lua,首选将整个值压栈,然后就可以在Lua中调用。
2、lua中提供正向和反向索引,区别在于证书永远是栈底,负数永远是栈顶。

在这里插入图片描述

2、基础练习

编译指令:g++ test.cpp -o test -llua -ldl

#include <iostream>  
#include <string.h>  
using namespace std;
 
extern "C"
{
#include "lua.h"  
#include "lauxlib.h"  
#include "lualib.h"  
}

// g++ test.cpp -o test  -llua -ldl
int main()
{
	//1.创建一个state  
	// luaL_newstate返回一个指向堆栈的指针
	lua_State *L = luaL_newstate();
 
	//2.入栈操作  
	lua_pushstring(L, "hello world");
	lua_pushnumber(L, 200);
 
	//3.取值操作  
	if (lua_isstring(L, 1)) {             //判断是否可以转为string  
		cout << lua_tostring(L, 1) << endl;  //转为string并返回  
	}
	if (lua_isnumber(L, 2)) {
		cout << lua_tonumber(L, 2) << endl;
	}
 
	//4.关闭state  
	lua_close(L);
	return 0;
}

在这里插入图片描述

2.1、加载Lua脚本并传递参数

编译指令:g++ test.cpp -o test -llua -ldl

函数说明:

1、函数用于将Lua脚本加载到Lua虚拟机中并进行编译
luaL_loadbuffer(L,s,sz,n)
	lua_State *L:Lua状态对象,表示Lua虚拟机的运行实例。
	const char *buff:指向Lua脚本内容的字符串。
	size_t sz:Lua脚本内容的长度。
	const char *name:可选参数,用于给脚本设置一个名称,便于调试和错误消息的输出。
	返回值:
		不为0表示有错误

2、函数用于调用Lua函数并处理其执行过程中可能发生的错误
lua_pcall(L,n,r,f)
	lua_State *L:Lua状态对象,表示Lua虚拟机的运行实例。
	int nargs:传递给Lua函数的参数数量。
	int nresults:期望的返回值数量。
	int errfunc:错误处理函数在调用栈中的索引。
	返回值:
		不为0表示有错误

3、函数用于从全局环境中获取一个全局变量,并将其值压入Lua栈顶
int lua_getglobal(lua_State *L, const char *name)
	lua_State *L:Lua状态对象,表示Lua虚拟机的运行实例。
	const char *name:要获取的全局变量的名称。

4、函数用于将一个数字(lua_Number类型)压入Lua栈顶
void lua_pushnumber(lua_State *L, lua_Number n)
	lua_State *L:Lua状态对象,表示Lua虚拟机的运行实例。
	lua_Number n:要压入栈的数字。

执行流程:
1、加载script脚本加载到lua虚拟机中
2、将脚本中的my_pow函数,压入到栈顶
3、压入my_pow需要的两个参数
4、执行脚本
5、获取脚本中的返回值

#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
    #include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
}

char const *script = R"(
function hello()
    print('hello world')
end

function my_pow(x,y)
    return x^y
end
)";

char const *script_1 = R"(
    pkg.hello()
)";

int main()
{
    /*
        加载脚本并传递参数
    */
    
    // 创建lua虚拟机,创建虚拟栈
    lua_State *state = luaL_newstate();
    // 打开lua标准库,以便正常使用lua api
    luaL_openlibs(state);
    {
        // 将lua脚本加载到虚拟机中,并编译
        auto rst = luaL_loadbuffer(state,script,strlen(script),"hello");
        // 判断是否加载成功
        if(rst !=0 ){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("load script faile:%s\n",msg);
                lua_pop(state,-1);
            }
            return -1;
        }
        // 执行加载并编译的Lua脚本
        if(lua_pcall(state,0,0,0)){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("load script faile:%s",msg);
                lua_pop(state,-1);
            }
        }

        // 从全局环境中获取一个my_pow函数压入到栈顶
        lua_getglobal(state,"my_pow");
        // 判断栈顶是不是一个函数,要是不是表示没有找到
        if(!lua_isfunction(state,-1)){
            printf("function  named my_pow not function\n");
            return -1;
        }
        // 将数字参数压入Lua栈中
        lua_pushnumber(state,2);
        lua_pushnumber(state,8);
        rst = lua_pcall(state,2,1,0);
        if(rst !=0 ){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("load script faile:%s\n",msg);
                lua_pop(state,-1);
            }
            return -1;
        }
        if(lua_isnumber(state,-1)){
            lua_Number val = lua_tonumber(state,-1);
            printf("%lf\n",val);
        }
    }
    lua_close(state);
    return 0;
}

2.2、加载脚本到stable(包)

编译命令: g++ main.cpp -o main -llua -ldl

#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
    #include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
}
char const *script = R"(
function hello()
    print('hello world')
end

function my_pow(x,y)
    return x^y
end
)";

/*   
	_G = {
    "helloworld" = function print("hello world")
    }
    _G = {
        "pkg" = {
            "helloworld" = function print("hello world")
        }
    }

    pkg.helloworld()
*/
    
char const *script_1 = R"(
    pkg.hello()
)";

int main()
{
    /*
        加载脚本到stable(包)
        1、生成chunk push到栈顶
        2、创建table,设置给_G表,_G["pkg"] = {}
        3、给这个table设置元表,元表继承_G的访问域(__index)
        4、执行code chunk
    */
    lua_State *state = luaL_newstate();
    luaL_openlibs(state);
    {
        auto rst = luaL_loadbuffer(state,script,strlen(script),"helloworld");
        if(rst != 0){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("load script faile:%s\n",msg);
                lua_pop(state,1);
            }
            return -1;
        }
        
        // 取出_G表
        lua_getglobal(state,"_G");
        if(lua_istable(state,-1)){  // chunk _G
            lua_newtable(state);    // 创建表 chunk _G new_stable
            lua_pushstring(state,"pkg"); // chunk _G new_stable pkg
            lua_pushvalue(state,-2); // chunk _G new_stable pkg new_stable
            lua_rawset(state,-4);   // chunk _G new_stable
            char const *upvalueName = lua_setupvalue(state,-3,1); // chunk _G
            lua_newtable(state);    // chunk _G metastable
            lua_pushstring(state,"__index");    // chunk _G metastable "__index"
            lua_pushvalue(state,-3); // chunk _G metastable "__index" _G
            lua_rawset(state,-3);   // chunk _G metastable
            lua_pushstring(state,"pkg");
            lua_rawget(state,-3);   // chunk _G metastable "pkg"(table)
            lua_pushvalue(state,-2);    // chunk _G metastable pkg(table) metastable
            lua_setmetatable(state,-2); // chunk _G metastable pkg(stable)
            lua_pop(state,3);   // chunk
        }
        // 执行chunk
        if(lua_pcall(state,0,0,0)){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("call function chunk failed:%s\n",msg);
                lua_pop(state,1);
            }
        }

        // 加载script_1
        rst = luaL_loadbuffer(state,script_1,strlen(script_1),"script_1");
        if(rst != 0){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("load script failed:%s\n",msg);
                lua_pop(state,1);
            }
            return -1;
        }

        if(lua_pcall(state,0,0,0)){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("call function chunk failed:%s\n",msg);
                lua_pop(state,1);
            }
        }
        lua_close(state);
    }
    return 0;
}

2.3、Lua调用c语言接口

#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
    #include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
}

int pow_from_c(lua_State *L)
{
    int param_count = lua_gettop(L);
    if(param_count != 2)
        return 0;
    
    if(lua_isinteger(L,1) && lua_isinteger(L,2)){
        auto x = lua_tointeger(L,1);
        auto y = lua_tointeger(L,2);
        int rst = (int)pow(x,y);
        lua_pushinteger(L,rst);
        return 1;
    }
    return 0;
}

char const *script_2 = R"(
    local val = pow_from_c(2,3)
    print(val)
)";
int main()
{
    // lua调用c语言接口
    lua_State *state = luaL_newstate();
    luaL_openlibs(state);
    {
        /*
            "_G" = {
                "pow_from_c" = pow_from_c
            }
        */
        lua_getglobal(state,"_G");
        lua_pushstring(state,"pow_from_c");
        lua_pushcclosure(state,pow_from_c,0);    // _G "pow_from_c"; closure
        lua_rawset(state,-3);   // _G
        lua_pop(state,1);   // _G
    }

    auto rst = luaL_loadbuffer(state,script_2,strlen(script_2),"script_2");
    if(rst != 0){
        if(lua_isstring(state,-1)){
            auto msg = lua_tostring(state,-1);
            printf("load script faile:%s\n",msg);
            lua_pop(state,1);
        }
        return -1;
    }

    if(lua_pcall(state,0,0,0)){
        if(lua_isstring(state,-1)){
            auto msg = lua_tostring(state,-1);
            printf("call function chunk failed:%s\n",msg);
            lua_pop(state,1);
        }
    }
    lua_close(state);
    return 0;
}

2.4、Lua实现面向对象

local anial_matestable = {
    __index = {
        walk = function (self)
            print(self,"我是walk")
        end,
        eat = function (self)
            print(self,"eat.")
        end,
    },

    __newindex = function (object,key,value)
        print("assigned "..value.."named "..key.."but not really")
    end,
}

function newobject()
    local objs = {name = "xxxx"}
    setmetatable(objs,anial_matestable)
    return objs
end

local obj = newobject()
obj.eat()
obj.walk()
obj.name = "abc"
obj.id = 0

2.5、向脚本中注册c++的类

#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
    #include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
}
char const *script_3 = R"(
    local obj_1 = create_game_object(1);
    local obj_2 = create_game_object(1);
    local obj_3 = create_game_object(2);
    local rst1 = obj_1:equal(obj_2)
    local rst2 = obj_1:equal(obj_3)
    print(rst1,";",rst2)
    print(""..obj_1:id())
)";

class GameObject{
private:
    u_int32_t _id;
public:
    static size_t registy_value;
public:
    GameObject(u_int32_t id):_id(id)
    {}
    u_int32_t id()const{
        return _id;
    }
    bool equal(GameObject *obj){
        return _id == obj->id();
    }
};
size_t GameObject::registy_value = 0;

int GameObject_equal(lua_State *state){
    int arg_count = lua_gettop(state);
    if(arg_count!=2){
        return 0;
    }

    if(lua_isuserdata(state,1) && lua_isuserdata(state,2)){
        void *userdata_self = lua_touserdata(state,1);
        void *userdata_that = lua_touserdata(state,2);
        GameObject *obj1 = (GameObject*)userdata_self;
        GameObject *obj2 = (GameObject*)userdata_that;
        auto rst = obj1->equal(obj2);
        lua_pushboolean(state,rst);
        return 1;
    }
    return 0;
}

int GameObject_id(lua_State* state){
    GameObject *this_obj = (GameObject*)lua_touserdata(state,1);
    auto rst = this_obj->id();
    lua_pushinteger(state,rst);
    return 1;
}

int create_game_object(lua_State* state){
    auto id = lua_tointeger(state,1);
    void *p = lua_newuserdata(state,sizeof(GameObject));
    GameObject *obj = new(p)GameObject(id);
    lua_rawgetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);
    lua_setmetatable(state,-2);
    return 1;
}

int main()
{
    // 怎么向脚本中注册c++的类
    // 使用userdata
    /*
        userdata:{
            metadata:{
                __index = {
                    equal = function(){},
                    id = function(){},
                }
            }
        }
    */
    lua_State *state = luaL_newstate();
    luaL_openlibs(state);
    {
        lua_getglobal(state,"_G");
        lua_pushstring(state,"create_game_object");
        lua_pushcclosure(state,create_game_object,0);
        lua_rawset(state,-3);
        lua_pop(state,1);

        lua_newtable(state);
        lua_pushstring(state,"__index");
        lua_newtable(state);
        lua_pushstring(state,"equal");
        lua_pushcclosure(state,GameObject_equal,0);
        lua_rawset(state,-3);
        lua_pushstring(state,"id");
        lua_pushcclosure(state,GameObject_id,0);
        lua_rawset(state,-3);
        lua_rawset(state,-3);

        lua_rawsetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);
        auto rst = luaL_loadbuffer(state,script_3,strlen(script_3),"oop");
        if(rst != 0){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("load script failed:%s\n",msg);
                lua_pop(state,1);
            }
            return -1;
        }
        // 执行
        if(lua_pcall(state,0,0,0)){
            if(lua_isstring(state,-1)){
                auto msg = lua_tostring(state,-1);
                printf("load script failed:%s\n",msg);
                lua_pop(state,1);
            }
        }
    }
    lua_close(state);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1130056.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入探究Selenium定位技巧及最佳实践

在使用Selenium进行Web自动化测试时&#xff0c;准确地定位元素是非常重要的一步。Selenium提供了多种元素定位方法&#xff0c;本文将深入探究这八大元素定位方法&#xff0c;帮助读者更好地理解和应用Selenium的定位技巧。 1. ID定位 ID是元素在HTML中的唯一标识符&#xff…

GitHub commit时出现 无法访问443 Operation timed out的解决办法

GitHub commit时出现 无法访问443 Operation timed out的解决办法 1.问题描述2. 环境3.解决方法4.如果上述方法不行&#xff0c;那就再试一试下面这个方法4.1 首先确认自己的网页可以打开github4.2 按照如下配置http和https代理4.2.1 找端口号 5. 参考链接 1.问题描述 当使用g…

STM32 PWM配置及呼吸灯

PWM的英文全称是"Pulse Width Modulation"&#xff0c;中文翻译为"脉冲宽度调制"。 在PWM中可以调节的其实只有两个东西&#xff0c;一个叫做可调周期&#xff08;调频率&#xff09;&#xff0c;另一个叫做占空比&#xff08;高电平/周期&#xff09;。 而…

一文说说自定义注解实现校验

自定义注解部分 /*** author 舒一笑* version 1.0.0* ClassName OvertimePlaceConver.java* Description 加班地址转化* createTime 2023年10月24日 22:22:00*/ Target(ElementType.FIELD) Retention(RetentionPolicy.RUNTIME) Constraint(validatedBy OvertimePlaceConvertV…

新款模块上线实现SIP模块与扩拨电话之间打点与喊话功能 IP矿用电话模块SV-2800VP

新款模块上线实现SIP模块与扩拨电话之间打点与喊话功能 IP矿用电话模块SV-2800VP 一、简介 SV-2800VP系列模块是我司设计研发的一款用于井下的矿用IP音频传输模块&#xff0c;可用此模块打造一套低延迟、高效率、高灵活和多扩展的IP矿用广播对讲系统&#xff0c;亦可对传统煤…

易基因: Nature Biotech:番茄细菌性青枯病的噬菌体联合治疗|国人佳作

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 生物防治是利用细菌接种剂来改变植物根际微生物群落的组成&#xff0c;但在以往研究中存在有接种的细菌在根际建立不良&#xff0c;与本地微生物组争夺资源&#xff0c;干扰本地微生物的…

程桌面管理软件Apple Remote Desktop mac中文介绍说明

Apple Remote Desktop mac是一款远程桌面管理软件。它可以让用户通过局域网或互联网连接到其他远程计算机&#xff0c;并实时监控和管理这些计算机。 使用Apple Remote Desktop&#xff0c;用户可以轻松远程操作和控制其他计算机的桌面。用户可以在远程计算机上查看、操控和键入…

vueDay03——可灵活变动的class样式

一、需求背景 有时候我们需要对不同身份的用户在同一个组件上展示不同的样式&#xff08;界面这里暂且不谈&#xff09;&#xff0c;我们就需要控制该组件在不同的数据下呈现不同的样式 这时候我们就可以使用:class属性来动态调整样式 二、将class与style绑定 我们可以这样…

Unity中从3D模型资产中批量提取材质

如何使用 只需在“项目”窗口中创建一个名为“编辑器”的文件夹&#xff0c;然后在其中添加此脚本即可。然后&#xff0c;打开Window-Batch Extract Materials&#xff0c;配置参数并点击“ Extract&#xff01; ”。 在Unity 2019.1上&#xff0c;可以将默认材质重映射条件配…

SpringBoot 分布式验证码登录方案

前言 为了防止验证系统被暴力破解&#xff0c;很多系统都增加了验证码效验&#xff0c;比较常见的就是图片二维码&#xff0c;业内比较安全的是短信验证码&#xff0c;当然还有一些拼图验证码&#xff0c;加入人工智能的二维码等等&#xff0c;我们今天的主题就是前后端分离的…

【C++】STL容器——【深浅拷贝】与【写时拷贝】对比详解(拷贝构造)(10)

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 目录 一.深浅拷贝浅拷贝&#xff1a;深拷贝&#xff1a; 二.写时拷贝 一.深浅拷贝 (默认拷贝构造运用 引用 防止死递归的后遗症&#…

基于C/C++的UG二次开发流程

文章目录 基于C/C的UG二次开发流程1 环境搭建1.1 新建工程1.2 项目属性设置1.3 添加入口函数并生成dll文件1.4 执行程序1.5 ufsta入口1.5.1 创建程序部署目录结构1.5.2 创建菜单文件1.5.3 设置系统环境变量1.5.4 制作对话框1.5.5 创建代码1.5.6 部署和执行 基于C/C的UG二次开发…

嚼一嚼Halcon中的3D手眼标定

文章目录 一、问题概述1、何为手眼标定&#xff1f;2、手眼标定的2种形式1&#xff09;眼在手上&#xff08;eye in hand&#xff09;&#xff1a;即相机固定在机械臂末端2&#xff09;眼在手外&#xff08;eye to hand&#xff09;&#xff1a;即相机固定在机械臂以外的地方 3…

【JVM】类的生命周期

【JVM】类的生命周期 文章目录 【JVM】类的生命周期1. 生命周期概述2. 加载阶段3. 连接阶段3.1 验证3.2 准备3.3 解析 4. 初始化阶段4.1 触发初始化的方式4.2 clinit不存在的情况4.3 多个类的初始化 5. 总结 1. 生命周期概述 类的生命周期分为5/7个阶段&#xff1a; 加载(Loa…

MSQL系列(八) Mysql实战-SQL存储引擎

Mysql实战-SQL存储引擎 前面我们讲解了索引的存储结构&#xff0c;BTree的索引结构&#xff0c;我们一般都知道Mysql的存储引擎有两种&#xff0c;MyISAM和InnoDB,今天我们来详细讲解下Mysql的存储引擎 文章目录 Mysql实战-SQL存储引擎1.存储引擎2.MyISAM的特点3. InnoDB的特…

面向小白vim使用手册

撤回上一步 按 "u" 注释多段 1&#xff1a;选择开始注释的地方&#xff0c;在命令模式下按 ctrv进入可视化模式。 2&#xff1a;鼠标向下滑动&#xff0c;选中要注释的段落&#xff1a;3:进入大写锁定&#xff0c;按"i"键进入插入模式&#xff1a; 4:输…

vue3 + ant design vue项目svg格式的background-image使用配置

直接使用的时候会报错: 图片解析不出来还是svg源文件代码 项目启动报错 vue3使用的时候普通配置会出现this.getOptions is not function错误&#xff08; Webpack 版本升级引起的&#xff0c;在较新的 Webpack 版本中&#xff0c;this.getOptions 方法已被移除。&#xff09;…

小知识(6) el-table表格选中行和回显行(vue3)

el-table表格选中行和回显行 官方文档说明 https://element-plus.org/zh-CN/component/table.html#table-%E6%96%B9%E6%B3%95 环境&#xff1a;vue3element-plus 选中行selection <el-table ref"baseTableRef" row-key"id" border :selection"tr…

支持多校 微信课表小程序源码 排课小程序源码 支持导入课表 情侣课表 背景设置

练手Lab课程表小程序源码是一个基于thinkphp系统进行开发的前后端分离系统。 源码功能介绍 1、情侣功能 2、情侣间留言 3、情侣间互相设置课程表背景 4、自己日、周课程表背景设置 5、教务系统课程表导入 6、导入别人分享的课表 7、导入别人分享的单课 8、多校支持 9…

25装饰器2

有一个比较绕的地方&#xff0c;但是我相信我能理解透彻这个里面的逻辑还有原理 def check(func):print(登录验证)def inner():func()return innerdef fss():print(发说说)fss check(fss) fss()这里的fss check(fss)还有后面的fss()什么意思&#xff1f;怎么理解呢&#xff…