菜鸟入门之lua与c++相互调用(包含多个demo)

前两篇文章中,已经介绍了使用vs2010编译lua5.1源码生成lua.lib 和 vs项目中使用c++调用lua,可以保证demo在vs上运行起来了。这里再详细介绍下c++和lua之间的相互调用以及原理。

c++与lua直接的调用,实际上通过一个栈结构来传递数据,该栈结构栈顶的索引值为-1,向栈底方向索引值依次为-1 ,-2......栈顶索引为1.栈结构里可以放函数,表,字符串,整形等各种lua的基本数据。

一、在当前cpp目录下创建test.lua文件,用于与c++交互调用,代码如下:

print("hello world  from lua file")
table1 = {}
table1["dinner"] = "rice"
table1["hahha"] = "ri123ce"
gScreenW = 1280;
function getIntegerSumFuncs(a ,b)
<span style="white-space:pre">	</span>return a + b
end
avg ,sum = average(10 ,20 ,30 ,40 ,50)

二、先熟悉下lua常用的C语言API。

int luaL_dofile (lua_State *L, const char *filename);//运行lua文件,L是当前已经创建的栈结构。返回0,运行文件正常;返回1,代表出现异常。

void lua_setglobal (lua_State *L, const char *name);//从堆栈上弹出一个值,并将其设到全局变量 name 中

void lua_getglobal (lua_State *L, const char *name);//把全局变量 name 里的值压入堆栈,栈顶值为-1。

const char *lua_tostring (lua_State *L, int index);//在栈L的索引值为index处取值并转化成C字符串(lua_tointeger等类似)

void lua_settop (lua_State *L, int index);//参数允许传入任何可接受的索引以及 0。它将把堆栈的栈顶设为这个索引。 如果新的栈顶比原来的大,超出部分的新元素将被填为 nil 。 如果 index 为 0 ,把栈上所有元素移除。

int lua_gettop (lua_State *L);//返回堆栈上的元素个数(返回 0 表示堆栈为空)

int lua_next (lua_State *L, int index);从栈上弹出一个 key(键), 然后把索引指定的表中 key-value(健值)对压入堆栈 (指定 key 后面的下一 (next) 对)。 如果表中以无更多元素, 那么 lua_next 将返回 0 (什么也不压入堆栈)。

void lua_pushinteger (lua_State *L, lua_Integer n);//把 n 作为一个数字压栈。

void lua_close (lua_State *L);//销毁指定 Lua 状态机中的所有对象

如果需要查询其他函数,推荐到Lua 5.1 参考手册,很详细也比较准确。

三、c++获取lua中的全局字符串。

//获取lua全局string
const char* getLuaGlobalString(char *fileName ,char *varName)
{
	lua_State *L = lua_open();
	luaL_openlibs(L);
	//加载并运行test.lua文件
	int isOpen = luaL_dofile(L ,fileName);
	if (isOpen == 0) {
		printf("error loading lua");
	}
	//将栈顶的索引设置为该index,如果index传0,移除栈上所有元素
	lua_settop(L ,0);
	//把全局变量 allGlobalChar 里的值压入堆栈。
	char *allGlobalChar = varName;
	lua_getglobal(L ,allGlobalChar); 

	int stateCode = lua_isstring(L ,1);
	if (stateCode != 1) {
		printf("open lua error code:%d" ,stateCode);
		return NULL;
	}
	const char* s = lua_tostring(L ,1);
	printf("get global screenW is:%s \n" ,s);
	lua_pop(L ,1);
	lua_close(L);
	return s;
}

调用代码:

getLuaGlobalString("test.lua" ,"gScreenW");

四、c++获取lua table中的的值

const char* getLuaVarOfTable(const char *fileName,const char *tableName ,const char *keyName)
{
	lua_State *L = lua_open();
	luaL_openlibs(L);
	int isOpen = luaL_dofile(L ,fileName);
	if (isOpen != 0)
	{
		printf("error open lua file");
		return NULL;
	}
	lua_settop(L ,0);//清空栈
	lua_getglobal(L ,tableName);

	int stateCode = lua_istable(L ,-1);//取栈顶
	if (stateCode != 1)
	{
		printf("get table failed code:%d" ,stateCode);
		return NULL;
	}
	lua_pushstring(L ,keyName);
	lua_gettable(L ,-2); //取栈顶下一个元素
	const char* valueStr = lua_tostring(L ,-1); //取栈顶
	printf("get lua table key-value %s-%s" ,keyName ,valueStr);
	lua_pop(L ,-1);
	return valueStr;
}

调用代码:

getLuaVarOfTable("test.lua" ,"table1" ,"dinner");

五、c++获取获取lua中的表

<pre name="code" class="java">string getLuaVarTable(const char* fileName ,const char *tableName ,char *result)
{
	lua_State *L = lua_open();
	luaL_openlibs(L);
	int isOpen = luaL_dofile(L ,fileName);
	if (isOpen != 0)
	{
		printf("error open lua file");
		return NULL;
	}
	lua_getglobal(L ,tableName);
	int size = lua_gettop(L);
	lua_pushnil(L);
	int index = 0;
	while(lua_next(L ,size))
	{
		const char* key = lua_tostring(L ,-2);//取栈顶下一个元素
		const char* value = lua_tostring(L , -1); //取栈顶
		//使用memcpy ,index记录地址游标
		memcpy(&result[index] ,key ,strlen(key));
		index += strlen(key);
		//因为sizeof取字符串,最后会有"/0"占一个字节,所以应该减去1
		memcpy(&result[index] ,"-" ,sizeof("-") - 1);
		index += 1;

		memcpy(&result[index] ,value ,strlen(value));
		index += strlen(value);
		lua_pop(L ,1);
	}
	result[index] = 0;
	cout <<"result is " << result << endl;
	//free(result);
	//printf("---%s" ,result.c_str);
	lua_pop(L ,1);
	return result;
}

调用代码:

char* reslut = (char*)malloc(100 * sizeof(char));
	getLuaVarTable("test.lua" ,"table1" ,reslut);
	free(reslut);

六、cpp调用lua中的函数

//要调用一个函数请遵循以下协议: 首先,要调用的函数应该被压入堆栈;
//	接着,把需要传递给这个函数的参数按正序压栈; 这是指第一个参数首先压栈。
//	最后调用一下 lua_call; nargs 是你压入堆栈的参数个数。
//	当函数调用完毕后,所有的参数以及函数本身都会出栈。 而函数的返回值这时则被压入堆栈。
//	返回值的个数将被调整为 nresults 个, 除非 nresults 被设置成 LUA_MULTRET。
//	在这种情况下,所有的返回值都被压入堆栈中。 Lua 会保证返回值都放入栈空间中。
//	函数返回值将按正序压栈(第一个返回值首先压栈), 因此在调用结束后,最后一个返回值将被放在栈顶。
const char* callLuaFunc(const char* fileName ,const char* functionName)
{
	lua_State *L = lua_open();
	luaL_openlibs(L);
	int isOpen = luaL_dofile(L ,fileName);
	if (isOpen != 0) {
		printf("error open lua file %s" ,fileName);
		return NULL;
	}
	lua_getglobal(L ,functionName);//如果表和函数重名,会怎么样
	lua_pushinteger(L ,12);
	lua_pushinteger(L ,3);
	//第一个参数:函数的个数 第二个参数:函数的返回值个数
	lua_call(L ,2 ,1);
	int result = lua_tointeger(L ,-1);
	printf("call lua func result : %d" ,result);
	return NULL;
}

调用代码:

callLuaFunc("test.lua" ,"getIntegerSumFuncs");

七、lua调用cpp函数计算平均值

//cpp计算平均值的函数
int average(lua_State* L)
{
	int n = lua_gettop(L);
	double sum = 0;
	int i;
	for (i = 1; i <= n; i ++)
	{
		if (!lua_isnumber(L ,i))
		{
			lua_pushstring(L ,"incorrect argument to avg");
			lua_error(L);
		}
		sum += lua_tonumber(L ,i);
	}
	lua_pushnumber(L ,sum / n);
	lua_pushnumber(L ,sum);
	//这里一定要返回元素个数,若返回0则找不到结果
	return 2;
}

//lua调用cpp计算平均值,调用入口
int averageMain()
{
	lua_State* L = lua_open();
	luaL_openlibs(L);
	//注册lua函数,实际上是将average push到栈结构,然后set average函数为global函数
	lua_register(L ,"average" ,average);
	//运行脚本
	luaL_dofile(L ,"test.lua");

	//把全局变量 avg 里的值压入堆栈
	lua_getglobal(L ,"avg");
	// 栈顶是-1,栈底是1
	cout << "cpp show: avg is " << lua_tointeger(L ,-1) <<endl;

	//从栈中弹出一个元素
	//lua_pop(L ,1);

	//把全局变量 sum 里的值压入堆栈
	lua_getglobal(L ,"sum");
	cout << "cpp show: sum is " << lua_tointeger(L ,-1) <<endl;

	//清除栈结构
	lua_close(L);
	return 0;
}

代码调用:

averageMain();

以上是c++和lua调用常用的demo。

这里附上工程实例下载地址: http://download.csdn.net/detail/wangbin_jxust/7809743

如果需要运行该工程,需要按照使用vs2010编译lua5.1源码生成lua.lib 配置一遍,然再运行。

时间: 2024-10-19 09:25:11

菜鸟入门之lua与c++相互调用(包含多个demo)的相关文章

lua编程之lua与C相互调用

lua是扩展性非常良好的语言,虽然核心非常精简,但是用户可以依靠lua库来实现大部分工作.除此之外,lua还可以通过与C函数相互调用来扩展程序功能.在C中嵌入lua脚本既可以让用户在不重新编译代码的情况下修改lua代码更新程序,也可以给用户提供一个自由定制的接口,这种方法遵循了机制与策略分离的原则.在lua中调用C函数可以提高程序的运行效率.lua与C的相互调用在工程中相当实用,本文就来讲解lua与C相互调用的方法. Lua与C相互调用的首要问题是如何交换数据,lua API使用了一个抽象的栈与

lua和C++相互调用

从lua调用C++函数和对象,利用LuaPlus可以方便的从C++中调用lua脚本,反过也一样.通过注册函数或类对象,lua便可以访问C++. 一.C风格函数注册    Lua提供了C风格的回调函数注册,该函数原型如下: int Callback(LuaState* state); 无论是全局函数.类非虚函数.类虚函数,只要符合上面的原型,都可以向Lua注册.我们以全局函数为例,下面是我们提供的一个回调函数CStyleAddFunc: int CStyleAddFunc(LuaState * s

Cocos2d-x3.0下 Lua与C++相互调用

这里讲下Lua与C++之间如何实现相互调用 原文连接:http://blog.csdn.net/qqmcy/article/details/26052771 DJLCData.h 实现类 // // DJLCData.h // uitestLua // // Created by 杜甲 on 14-5-17. // // #ifndef __uitestLua__DJLCData__ #define __uitestLua__DJLCData__ #include "cocos2d.h"

Lua与C++相互调用

{--1.环境--} 为了快速入手,使用了小巧快速的vc++6.0编译器 以及在官网下载了Lua安装包..官网地址{--http://10.21.210.18/seeyon/index.jsp--} 两者都安装好后,即可进行 {--2.工程以及配置--} 1.首先用vc++6.0创建一个简单的win32 console application 2.从Lua的安装目录下复制include和lib两个目录下的文件到刚刚创建的工程的目录下. {include:包含了lua的.h头文件} {lib:包含

uLua学习笔记(三):Unity3D和Lua之间的相互调用

这篇笔记主要集中学习一下uLua和Unity3D之间相互调用的方法,我们导入了uLua之后,现在会弹出一个类似学习屏幕的东西,如下: 先赞一个! Unity3D调用Lua Unity3D调用Lua的方法还是比较简单的,所以先说这个,由于这部分在学习笔记(一)中已经说的挺多的了,更多的内容点击这里回去看,所以这里我们就来看一个简单的示例即可: 1 using LuaInterface; 2 using UnityEngine; 3 4 public class UnityCallLua : Mon

C#与lua相互调用

Lua是一种很好的扩展性语言,Lua解释器被设计成一个很容易嵌入到宿主程序的库.LuaInterface则用于实现Lua和CLR的混合编程. (一)C#调用Lua 测试环境:在VS2015中建一个C#控制台应用程序,并添加LuaInterface.dll的引用 LuaInterface下载地址:http://luaforge.net/projects/luainterface/ (下载luainterface-1.5.3,这里面的资源比较多) LuaInterface.Lua类是CLR访问Lua

C程序与Lua脚本相互调用

Lua脚本是一种可用于C程序开发/测试的工具,本篇介绍一下C程序与Lua脚本如何进行相互调用,更加详细的操作参见<Programing in Lua>.本文分为3个部分:1.Windows环境下Lua的下载以及安装注意事项:2.Visual C++6.0中Lua的配置:3.C程序与Lua脚本相互调用实例. 1.Windows环境下Lua的下载以及安装注意事项 a.下载Lua for Windows,笔者用的版本是V5.1.4-35: b.上微软官网,下载Visual C++运行库——vcred

Lua与C的相互调用

闲的蛋疼,让C和Lua玩包剪锤.结果C以微弱的优势胜出了. 言归正传,这次主要是想练习Lua和C的相互调用. 一.C调用Lua函数 1. luaL_dofile(L, fn); 该函数可以让Lua虚拟栈读取路径为fn的Lua文件,其实质是: lua_loadfile(L, fn) || lua_pcall(L, 0, Lua_MUTIRET, 0) 实际上,lua_loadfile只是把Lua文件加载到VM,成为一个可执行的对象,但却还没有执行它,所以还不能使用. 而lua_pcall则把该Lu

Lua学习笔记6:C++和Lua的相互调用

Lua版本:5.2.3 一 C++ 调用Lua 1 目录结构 CppCallLua { main.cpp script{ test.lua } lualia{ lua.h lualib.h laux.lib.h luaconf.h liblua.a } } 2 代码 //main.cpp #include <iostream> extern "C" { #include "lualib/lua.h" #include "lualib/luali