Lua与C++交互

这篇具有很好参考价值的文章主要介绍了Lua与C++交互。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、Lua和C++交互

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

Lua与C++交互,Linux 系统编程,1024程序员节,原力计划

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;
}

Lua与C++交互,Linux 系统编程,1024程序员节,原力计划

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文章来源地址https://www.toymoban.com/news/detail-714985.html

#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;
}

到了这里,关于Lua与C++交互的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 1024程序员节特辑:【Spring Boot自动配置原理揭秘】

    主页传送门:📀 传送   Spring Boot 是一个用于创建独立的、生产级别的 Spring 应用程序的框架。它极大地简化了 Spring 应用程序的开发过程,其中一个关键的功能就是自动配置(Auto-Configuration)。   自动配置可以根据项目需求自动配置各种服务和组件,它可以帮助开发者

    2024年02月08日
    浏览(69)
  • c++学习笔记-提高编程-模板(哔站-黑马程序员c++教学视频)

    通用的模具,提高代码复用性 不可以直接使用,只是一个框架;模板的通用性并不是万能的。 3.2.1 函数模板 函数模板的作用:建立一个通用函数,其函数返回值类型和参数类型可以不具体确定,用一个虚拟的类型来代表。 1)语法: templatetypename T//函数声明或定义 函数 temp

    2023年04月11日
    浏览(85)
  • 好用且免费的CodeWhisperer,给1024程序员节送礼来了

          国庆期间没有胆量去人从众的景点,关在家里刷手机时意外在亚马逊的User Group公众号上发现了CodeWhisperer这么个好东西(bu yao qian),以后撸代码也可以提高生产力(fang yang mo yu)了,这还不赶紧上手试一下。看官方介绍说它支持流行的IDE开发工具,包括VS Code、Intelli

    2024年02月08日
    浏览(54)
  • 1024程序员节带你玩转图片Exif信息获取之JavaScript

    目录 一、前言 二、背景 三、Exif.js          1、Exif.js 简介 2、Exif.js 引入 四、多场景展示数据获取 1、原始图片直接获取  2、base64 编码文件加载  3、文件上传的方式加载  五、总结        1024是2的十次方,二进制计数的基本计量单位之一。1G=1024M,而1G与1级谐音,也有一

    2024年02月20日
    浏览(60)
  • 1024程序员节特辑 | Spring Boot实战 之 MongoDB分片或复制集操作

    Spring实战系列文章: Spring实战 | Spring AOP核心秘笈之葵花宝典 Spring实战 | Spring IOC不能说的秘密? 国庆中秋特辑系列文章: 国庆中秋特辑(八)Spring Boot项目如何使用JPA 国庆中秋特辑(七)Java软件工程师常见20道编程面试题 国庆中秋特辑(六)大学生常见30道宝藏编程面试题

    2024年02月08日
    浏览(82)
  • 1024程序员狂欢节 | IT前沿技术、人工智能、数据挖掘、网络空间安全技术

    一年一度的1024程序员狂欢节又到啦!成为更卓越的自己,坚持阅读和学习,别给自己留遗憾,行动起来吧! 那么,都有哪些好书值得入手呢?小编为大家整理了前沿技术、人工智能、集成电路科学与芯片技术、新一代信息与通信技术、网络空间安全技术,四大热点领域近期

    2024年02月06日
    浏览(67)
  • 1024程序员节特辑 | ELK+ 用户画像构建个性化推荐引擎,智能实现“千人千面”

    专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https://blog.csdn.net/superdangbo/category_9271502.html tensorflow专栏:https://blog.csdn.net/superdangbo/category_869

    2024年02月07日
    浏览(84)
  • # Lua与C++交互(二)———— 交互

    基础调用 再来温习一下 myName = “beauty girl” C++想要获取myName的值,根据规则,它需要把myName压入栈中,这样lua就能看到; lua从堆栈中获取myName的值,此时栈顶为空; lua拿着myName去全局表中查找与之对应的字符串; 全局表找到,并返回\\\"beauty girl\\\"; lua把\\\"beauty girl\\\"压入栈中;

    2024年02月11日
    浏览(36)
  • 1024程序员节?我们整点AI绘图玩玩吧,一文教你配置stable-diffusion

    需提前准备:一台高性能的电脑(尤其是显存)、python、Git、梯子。 其实Github上有很多关于Stable diffusion的库,综合对比之后,我选取的是比较全面的AUTOMATIC1111这个,源码链接:Stable-diffusion(Github) 找到安装那块的教程,此教程以windows为例。 ps:如果你电脑上已经有了pyt

    2024年01月16日
    浏览(74)
  • PHP框架开发实践 | 1024 程序员节:通过index.php找到对应的controller是如何实现的

    🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于PHP专栏:PHP进阶实战教程。 🎉欢迎 👍点赞✍评论⭐收藏

    2024年02月08日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包