天天看點

lua和C++互相交換資料

下面的代碼示範了在C++和lua腳本之間傳遞資料。

首先在C++中建立一個table,添加元素,然後放置到lua的全局表中。在lua腳本中可以使用C++建立的這個表。

然後在腳本中建立一個表,以腳本傳回值的方式傳回給C++,在C++中可以讀取表中的值。

例子代碼需要一個args.lua的lua檔案,要手工建立,我把它放到了C槽根目錄下。

// cpplua.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

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

/* args.lua檔案的内容
io.write( "[lua] These args were passed into the script from C/n" );

for i=1,table.getn(arg) do
print(i,arg[i])
end

io.write("[lua] Script returning data back to C/n")

local temp = {}
temp[1]=9
temp[2]=8
temp[3]=7
temp[4]=6
temp[5]=5
temp["test1 key"]="test1 value"
temp[6]="test 6"
temp["test 99"]=99

for i,n in pairs(temp)
do 
print (i,n)
end

return temp,9,1

*/
int _tmain(int argc, _TCHAR* argv[])
{
	int status;

	// lua_open: 建立一個新的lua環境
	lua_State* state = lua_open();

	// 在state環境上打開标準庫,
	// 标準庫包括:
	// luaopen_base
	// luaopen_package
	// luaopen_table
	// luaopen_io
	// luaopen_os
	// luaopen_string
	// luaopen_math
	// luaopen_debug
	luaL_openlibs(state);  /* open libraries */

	status = luaL_loadfile( state, "c://args.lua" );

	std::cout << "[C++] Passing 'arg' array to script" << std::endl;

	// 建立一個新的表
	lua_newtable( state );

	//
	// set first element "1" to value 45
	//
	// 調用lua的函數,都是通過壓棧出棧來完成的
	// 為表執行一個t[k]=v的操作,則需要先将k壓棧,再将v壓棧,再調用操作函數
	// lua_rawset直接指派(不觸發metamethods方法)。 
	
	// lua_rawset/lua_settable使用:
	// 它從棧中擷取參數。以table在棧中的索引作為參數,
	// 并将棧中的key和value出棧。
	// lua_pushnumber函數調用之前,
	// table是在棧頂位置(索引為-1)。index和value入棧之後,
	// table索引變為-3。
	lua_pushnumber( state, 1 );
	lua_pushnumber( state, 45 );
	lua_rawset( state, -3 );

	// set second element "2" to value 99
	lua_pushnumber( state, 2 );
	lua_pushnumber( state, 99 );
	lua_rawset( state, -3 );

	// set the number of elements (index to the last array element)
	// lua_pushliteral壓入一個字元串,不需要指定長度
	// 如果lua_pushlstring,則需要指定長度
	lua_pushliteral( state, "n" );
	lua_pushnumber( state, 2 );
	lua_rawset( state, -3 );

	// set the name of the array that the script will access
	// Pops a value from the stack and sets it as the new value of global name.
	// 從棧頂彈出一個值,并将其設定全局變量"arg"的新值。
	lua_setglobal( state, "arg" );


	std::cout << "[C++] Running script" << std::endl;

	int result = 0;
	if (status == 0)
	{
		result = lua_pcall( state, 0, LUA_MULTRET, 0 );
	}
	else
	{
		std::cout << "bad" << std::endl;
	}

	if (result != 0)
	{
		std::cerr << "[C++] script failed" << std::endl;
	}

	std::cout << "[C++] These values were returned from the script" << std::endl;

	// lua_gettop傳回棧頂的索引
	// 如果索引為0,則表示棧為空
	while (lua_gettop( state ))
	{
		switch (lua_type( state, lua_gettop( state ) ))
		{
		case LUA_TNUMBER:
			{
				std::cout << "script returned " << lua_tonumber( state, lua_gettop( state ) ) << std::endl; 
				break;
			}
		case LUA_TTABLE:  
			{
				std::cout << "script returned a table" << std::endl; 
				
				// 簡單的周遊表的功能
				// ***好像lua不儲存表的元素的添加順序***

				// 壓入第一個鍵
				lua_pushnil(state);  /* 第一個 key */
				int t = -2;
				while (lua_next(state, t) != 0)
				{
					/* 'key' (索引-2) 和 'value' (索引-1) */
					const char* key = "unknown";
					const char* value;
					if(lua_type(state, -2) == LUA_TSTRING)
					{
						key = lua_tostring(state, -2);
						value = lua_tostring(state, -1);
					}
					else if(lua_type(state, -2) == LUA_TNUMBER)
					{
						// 因為lua_tostring會更改棧上的元素,
						// 是以不能直接在key上進行lua_tostring
						// 是以,複制一個key,壓入棧頂,進行lua_tostring
						lua_pushvalue(state, -2);
						key = lua_tostring(state, -1);
						lua_pop(state, 1);
						value = lua_tostring(state, -1);
					}
					else
					{
						value = lua_tostring(state, -1);
					}

					std::cout   <<"key="<< key 
								<< ", value=" << value << std::endl;

					/* 移除 'value' ;保留 'key' 做下一次疊代 */
					lua_pop(state, 1);
				}

				break;
			}
		case LUA_TSTRING: 
			{
				std::cout << "script returned " << lua_tostring( state, lua_gettop( state ) ) << std::endl;
				break;
			}
		case LUA_TBOOLEAN:
			{
				std::cout << "script returned " << lua_toboolean( state, lua_gettop( state ) ) << std::endl;
				break;
			}
		default: 
			std::cout << "script returned unknown param" << std::endl; 
			break;
		}
		lua_pop( state, 1 );
	}
	lua_close( state );
	return 0;
}
           

本例用了一個控制台工程,輸出如下:

[C++] Passing 'arg' array to script

[C++] Running script

[lua] These args were passed into the script from C

1       45

2       99

[lua] Script returning data back to C

1       9

2       8

3       7

4       6

5       5

6       test 6

test 99 99

test1 key       test1 value

[C++] These values were returned from the script

script returned 1

script returned 9

script returned a table

key=1, value=9

key=2, value=8

key=3, value=7

key=4, value=6

key=5, value=5

key=6, value=test 6

key=test 99, value=99

key=test1 key, value=test1 value

繼續閱讀