lua调用C++函数

第一步搭建lua的环境.

win10 lua环境搭建-CSDN博客

我使用的环境是win10+vs2015+lua54

先来个最简单的lua调用C++函数,

无参数无返回值的

第一步:定义C++函数.

int CTest(lua_State* L) // 返回值是固定的int类型,返回0表示没有返回参数,返回1表示有一个返回参数
{
	std::cout << "int CTest" << std::endl;
	return 0;
}

这个函数,除了函数名可以自己定义其他的都要按这个来定义.

返回值是固定的int类型,返回0表示没有返回参数,返回1表示有一个返回参数.

第二步:注册函数.

lua_register(lua,"CTest",CTest); 

第一个参数是lua的lua_State的指针,第二个是lua的注册函数名字,这个名字是在lua代码里使用的,第三个参数是函数指针就是刚才定义的C++函数.

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

int CTest(lua_State* L) // 返回值是固定的int类型,返回0表示没有返回参数,返回1表示有一个返回参数
{
	std::cout << "int CTest" << std::endl;
	return 0;
}

int main()
{
	lua_State *lua = luaL_newstate();
	luaopen_base(lua);
	luaopen_string(lua);
	lua_register(lua,"CTest",CTest); //第一个参数是lua状态指针,第二个参数是函数名称,第三个参数是lua函数指针,第二个参数和第三个参数可以用不同的名字,但第三个必须使用正确的函数指针
	luaL_loadfile(lua, "D:\\code\\MyCode\\C++\\Lua\\CPPAddLua\\testLua\\x64\\Debug\\main.lua");
	lua_pcall(lua, 0,0,0);
	getchar();
	return 0;
}

直接运行

这样就是lua调用到了C++函数.当然这里lua调用C++ 函数是指在C++代码中的调用.

lua传递参数,没有返回值

只需要从lua的堆栈拿出一个参数即可.在此之前还需要再注册一下.

lua_register(lua, "CTestToString", CTestToString);
const char* luaStr = lua_tostring(L,1);

 这样得到的就是lua传递的参数.

int CTestToString(lua_State* L)
{
	const char* luaStr = lua_tostring(L,1);
	std::cout << luaStr << std::endl;
	return 0;
}

 

 传第二个参数就再获取一下第二个参数.

 

int num = lua_tointeger(L,2);
int CTestToString(lua_State* L)
{
	const char* luaStr = lua_tostring(L,1);
	std::cout << luaStr << std::endl;
	int num = lua_tointeger(L,2);
	std::cout << num << std::endl;
	return 0;
}

 

传递普通参数就这样传递.

lua传递数组给C++函数

第一步注册函数:

lua_register(lua, "CTestArr", CTestArr);

第二步:编写接收函数

int CTestArr(lua_State* L)
{
	std::vector<std::string> vStr;
	std::cout << "int CTestArr" << std::endl;
	int arraySize = luaL_len(L, 1); //获取表的大小
	for (int i = 1; i <= arraySize; ++i)
	{
		lua_pushnumber(L,i);	//往栈中压入一个数字,表示从数组中取那个下标的值,lua都是从1开始的所以i从1开始
		lua_gettable(L, 1);		//把上一行索引的位置出栈,再把i压入 栈
		vStr.push_back(lua_tostring(L,-1));
		lua_pop(L,1);
	}
	for (auto& value : vStr)
	{
		std::cout << value << std::endl;
	}
	return 0;
}

第三步:lua调用

.

lua传递表给C++函数

lua_next3(L,3)

  1. 先从栈顶弹出一个key
  2. 从栈指定位置的table里取下一对key-value,先将key入栈再将value入栈
  3. 如果第2步成功则返回非0值,否则返回0,并且不向栈中压入任何值.

第一步注册函数:

lua_register(lua, "CTestTable", CTestTable);

第二步:

int CTestTable(lua_State* L)
{
	std::cout << "int CTestTable" << std::endl;
	std::map<std::string, std::string> mStr;
	lua_pushnil(L);
	while (lua_next(L, 1) != 0)
	{
		mStr[lua_tostring(L, -2)] = lua_tostring(L,-1);
		lua_pop(L,1);
	}
	for (auto& value : mStr)
	{
		std::cout << value.first << " = " << value.second << std::endl;
	}
	return 0;
}

第三步lua调用:

 结果:

lua调用C++ 获取表中的内容

	lua_getfield(L,1,"name");
	std::cout << lua_tostring(L,-1) << std::endl;

Lua调用C++参数类型检查

	luaL_checktype(L,1,LUA_TBOOLEAN);


	if (lua_type(L, 1) != LUA_TBOOLEAN)
	{
		luaL_argerror(L,1,"bad argument");
	}

第一行,一旦不匹配代码就不会往下执行,

第二行的不匹配还会往下执行.

Lua调用C++ 返回值普通类型

第一步:注册函数:

lua_register(lua, "TestRe", TestRe);

第二步写函数:

int TestRe(lua_State* L)
{
	lua_pushstring(L,"return value");
	return 1;
}

一个返回参数就返回1,两个就返回2

第三步lua代码

结果:

lua返回表

第一步注册函数:

lua_register(lua, "TestReTable", TestReTable);

第二步写注册函数

int TestReTable(lua_State* L)
{
	lua_newtable(L);  // 创建一个表格,放在栈顶
	lua_pushstring(L,"name"); // 压入key
	lua_pushstring(L,"ccname");//压入value
	lua_settable(L,-3); //弹出key value,并设置到表,表在栈顶了作为返回值
	lua_pushstring(L, "age"); // 压入key
	lua_pushinteger(L, 21);//压入value
	lua_settable(L, -3); //弹出key value,并设置到表,表在栈顶了作为返回值
	return 1;
}

第三步:lua

结果:

C++全部代码:

#include <iostream>
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include <vector>
#include <string>
#include <map>


int CTest(lua_State* L) // 返回值是固定的int类型,返回0表示没有返回参数,返回1表示有一个返回参数
{
	std::cout << "int CTest" << std::endl;
	return 0;
}

int CTestToString(lua_State* L)
{
	const char* luaStr = lua_tostring(L,1);
	std::cout << luaStr << std::endl;
	int num = lua_tointeger(L,2);
	std::cout << num << std::endl;
	bool is = lua_toboolean(L, 3);
	std::cout << is << std::endl;
	return 0;
}

int CTestArr(lua_State* L)
{
	std::vector<std::string> vStr;
	std::cout << "int CTestArr" << std::endl;
	int arraySize = luaL_len(L, 1); //获取表的大小
	for (int i = 1; i <= arraySize; ++i)
	{
		lua_pushnumber(L,i);	//往栈中压入一个数字,表示从数组中取那个下标的值,lua都是从1开始的所以i从1开始
		lua_gettable(L, 1);		//把上一行索引的位置出栈,再把i压入 栈
		vStr.push_back(lua_tostring(L,-1));
		lua_pop(L,1);
	}
	for (auto& value : vStr)
	{
		std::cout << value << std::endl;
	}
	return 0;
}

int CTestTable(lua_State* L)
{
	std::cout << "int CTestTable" << std::endl;
	/*   读取全部的表的内容 */
	std::map<std::string, std::string> mStr;
	lua_pushnil(L);
	while (lua_next(L, 1) != 0)
	{
		mStr[lua_tostring(L, -2)] = lua_tostring(L,-1);
		lua_pop(L,1);
	}
	for (auto& value : mStr)
	{
		std::cout << value.first << " = " << value.second << std::endl;
	}

	/* 只取一个
	lua_getfield(L,1,"name");
	std::cout << lua_tostring(L,-1) << std::endl;
	*/
	return 0;
}


int TestRe(lua_State* L)
{
	lua_pushstring(L,"return value");
	return 1;
}


int TestReTable(lua_State* L)
{
	lua_newtable(L);  // 创建一个表格,放在栈顶
	lua_pushstring(L,"name"); // 压入key
	lua_pushstring(L,"ccname");//压入value
	lua_settable(L,-3); //弹出key value,并设置到表,表在栈顶了作为返回值
	lua_pushstring(L, "age"); // 压入key
	lua_pushinteger(L, 21);//压入value
	lua_settable(L, -3); //弹出key value,并设置到表,表在栈顶了作为返回值
	return 1;
}

int main()
{
	lua_State *lua = luaL_newstate();
	luaopen_base(lua);
	luaopen_string(lua);
	lua_register(lua,"CTest",CTest); //第一个参数是lua状态指针,第二个参数是函数名称,第三个参数是lua函数指针,第二个参数和第三个参数可以用不同的名字,但第三个必须使用正确的函数指针
	lua_register(lua, "CTestToString", CTestToString);
	lua_register(lua, "CTestArr", CTestArr);
	lua_register(lua, "CTestTable", CTestTable);
	lua_register(lua, "TestRe", TestRe);
	lua_register(lua, "TestReTable", TestReTable);
	luaL_loadfile(lua, "D:\\code\\MyCode\\C++\\Lua\\CPPAddLua\\testLua\\x64\\Debug\\main.lua");
	lua_pcall(lua, 0,0,0);
	getchar();
	return 0;
}

lua全部代码:

CTest()

CTestToString("lua string",123456,true)
local arr = {"A001","A002","A003"};
CTestArr(arr)
local tab = {name="xiaoming",age="22",id="007"};
CTestTable(tab)

local re = TestRe()
print("re = " .. re)

local retab = TestReTable()
print("name = " .. retab["name"])
print("name = " .. retab["age"])

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

模型部署 - BevFusion - (1) - 思路总结

模型部署实践 - BevFusion 思路总结一、网络结构 - 总结1.1、代码1.2、网络流程图1.3、模块大致梳理 二、Onnx 的导出 -总体思路分析三、优化思路总结 学习 BevFusion 的部署&#xff0c;看了很多的资料&#xff0c;这篇博客进行总结和记录自己的实践 思路总结 对于一个模型我…

自学高效备考2025年AMC8数学竞赛:2000-2024年AMC8真题解析

今天继续来随机看五道AMC8的真题和解析&#xff0c;根据实践经验&#xff0c;对于想了解或者加AMC8美国数学竞赛的孩子来说&#xff0c;吃透AMC8历年真题是备考最科学、最有效的方法之一。下面的五道题目如果你能在8分钟内做对&#xff08;主要结果对&#xff0c;无需过程&…

【C++精简版回顾】18.文件操作

1.文件操作头文件 2.操作文件所用到的函数 1.文件io 1.头文件 #include<fstream> 2.打开文件 &#xff08;1&#xff09;函数名 文件对象.open &#xff08;2&#xff09;函数参数 /* ios::out 可读 ios::in 可…

Vue前端+快速入门【详解】

目录 1.Vue概述 2. 快速入门 3. Vue指令 4.表格信息案例 5. 生命周期 1.Vue概述 1.MVVM思想 原始HTMLCSSJavaScript开发存在的问题&#xff1a;操作麻烦&#xff0c;耦合性强 为了实现html标签与数据的解耦&#xff0c;前端开发中提供了MVVM思想&#xff1a;即Model-Vi…

Spring框架精髓:带你手写IoC

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

巧用二进制实现俄罗斯方块小游戏

效果预览 思想 首先建立两个数组board、tetris用来存储当前已经堆积在棋盘的方块与正在下落的方块。 这两个是一维数组当需要在页面画棋盘时就对其每一项转成二进制&#xff08;看计算属性tetrisBoard&#xff09;&#xff0c;其中1&#xff08;红色&#xff09;0&#xff08;…

python celery beat实现定时任务

在Celery在python中的应用除了实现异步任务&#xff08;async task)外也可以执行定时任务(beat) 1.Celery定时任务是什么&#xff1f; Celery默认任务单元由任务生产者触发,但有时可能需要其自动触发, 而beat进程正是负责此类任务,能够自动触发定时/周期性任务. 只需要在配置…

yolov5训练太慢的解决方案

问题原因 训练太慢大多是因为没有安装CUDA和pytorch&#xff0c;导致的只有cpu在跑&#xff0c;显卡没跑 这就是很典型的。 解决方案 第一步&#xff1a;安装CUDA 在本机上面安装CUDA,记住只有N卡可以安装&#xff0c;一开始的电脑是自带CUDA的。 如果不是自带的CUDA&…

NoSQL--2.MongoDB配置

目录 2.MongdoDB配置 2.1 Windows环境下操作 2.1.1 注册MongDB Atlas&#xff1a; 2.1.2 MongoDB Community Server Download&#xff1a; 2.1.3 启动MondgoDB服务&#xff1a; 2.1.3.1 命令行参数的方式启动MongoDB服务&#xff1a; 2.1.3.2 使用配置文件方式启动Mongo…

游戏框架搭建

使用框架的目标&#xff1a;低耦合&#xff0c;高内聚&#xff0c;表现和数据分离 耦合&#xff1a;对象&#xff0c;类的双向引用&#xff0c;循环引用 内聚&#xff1a;相同类型的代码放在一起 表现和数据分离&#xff1a;需要共享的数据放在Model里 对象之间的交互一般有三…

如何使用恢复软件恢复删除的文件?回收站文件恢复攻略

随着计算机在日常生活中的普及&#xff0c;文件的管理和存储成为我们不可或缺的技能。在Windows操作系统中&#xff0c;回收站作为一个帮助我们管理文件删除的重要工具&#xff0c;在误删了一些重要文件之后&#xff0c;我们可能会因为找不到回收站中恢复的文件而感到困惑。本文…

革命文物的新征程:SpringBoot实践

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

打造个人知识库-chatwithrtx接口研究

前言 之前安装了chatwithrtx&#xff0c;确实挺好用的。但是如果想用其对外提供服务的话&#xff0c;还需要研究是否能够提供api接口进行调用&#xff0c;所以今天来进行一下研究。 gradio介绍 web的访问是通过gradio框架进行开发的。在user_interface.py中可以发现如下引用 im…

第十六天-爬虫selenium库

目录 1.介绍 2.使用 selenium 1.安装 2.使用 1.测试打开网页&#xff0c;抓取雷速体育日职乙信息 2.通过xpath查找 3.输入文本框内容 send_keys 4.点击事件 click 5.获取网页源码&#xff1a; 6.获取cookies 7.seleniumt提供元素定位方式&#xff1a;8种 8.控制浏览…

算法刷题day20:二分

目录 引言概念一、借教室二、分巧克力三、管道四、技能升级五、冶炼金属六、数的范围七、最佳牛围栏 引言 这几天一直在做二分的题&#xff0c;都是上了难度的题目&#xff0c;本来以为自己的二分水平已经非常熟悉了&#xff0c;没想到还是糊涂了一两天才重新想清楚&#xff0…

Linux红帽rhce认证多少钱?考个RHCE难不难?

Linux作为开源操作系统的佼佼者&#xff0c;已经广泛应用于各个领域。红帽认证工程师(Red Hat Certified Engineer&#xff0c;简称RHCE)作为Linux领域权威的认证之一&#xff0c;自然成为了众多IT从业者追求的目标。那么&#xff0c;RHCE认证的培训费用是多少?考取这一认证又…

【C语言】linux内核packet_setsockopt

一、中文注释 // 发送数据包函数。它尝试通过特定的网络设备队列直接传输一个skb&#xff08;socket缓冲区&#xff09;。 static int packet_direct_xmit(struct sk_buff *skb) {return dev_direct_xmit(skb, packet_pick_tx_queue(skb)); // 调用dev_direct_xmit函数&#x…

写代码实现基金回测(一)

参考博客&#xff1a;应用实战&#xff1a;我的第一个开源项目-基金定投回测工具 这个博主的代码的目录结构还是很赞的 看一下他是如何计算收益率的 第一步&#xff1a;获取所有公募基金的基础信息 共计一万个基金 第二步&#xff1a;获取所有基金的费率信息 这里有一点需要…

Java基于springboot的个人理财系统

基于springboot的个人理财系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了个人理财系统的开发全过程。通过分析个人理财系统管理的不足&#xff0c;创建了一个计算机管理个人理财系统的方案。文章介绍了个…