加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

介绍LuaPlus: 好用的Lua For C++扩展(修订)

发布时间:2020-12-14 22:18:43 所属栏目:大数据 来源:网络整理
导读:本文版权归 博客园 沐枫?所有,转载请按如下方式详细标明原创作者及出处,以示尊重!! 作者: 沐枫 原文: http://www.cnblogs.com/ly4cn/archive/2005/11/27/285439.html ? LuaPlus是Lua的C++增强,也就是说,LuaPlus本身就是在Lua的源码上进行增强得来的
本文版权归 博客园 沐枫?所有,转载请按如下方式详细标明原创作者及出处,以示尊重!!
作者: 沐枫
原文: http://www.cnblogs.com/ly4cn/archive/2005/11/27/285439.html
?
LuaPlus是Lua的C++增强,也就是说,LuaPlus本身就是在Lua的源码上进行增强得来的。用它与C++进行合作,是比较好的一个选择。
LuaPlus目前版本为:LuaPlus for Lua 5.01 Distribution Build 1080 (February 28,2004)。大家可以到 http://luaplus.org/ 站点下载:
源码?? ( http://wwhiz.com/LuaPlus/LuaPlus50_Build1081.zip)
目标码 ( http://wwhiz.com/LuaPlus/LuaPlus50_Build1081_Win32Binaries.zip)

介绍LuaPlus: 好用的Lua For C++扩展?????沐枫网志

[由于lua内核升级到5.1,因此,luaplus也同样跟着升级。最新的luaplus可以通过svn获取,地址 svn://svn.luaplus.org/LuaPlus/work51,
同时,luaplus基于5.0的内核仍然在维护更新,也可以通过svn获取,地址 svn://svn.luaplus.org/root/LuaPlus/Dev ]

我将在下面说明,如何使用LuaPlus,以及如何更方便的让LuaPlus与C++的类合作无间。

1. 调用Lua脚本

?

???? // ?创建Lua解释器:

????LuaStateOwner?state;?

????

????
// ?执行Lua脚本:

????state -> DoString( " print('Hello?Worldn') " );

????
// ?载入Lua脚本文件并执行:

????state -> DoFile( " C:test.lua " );

????
// ?载入编译后的Lua脚本文件并执行:

????state -> DoFile( " C:test.luac " );


2. 与Lua脚本互相调用

???? // ?为Lua脚本设置变量

????state -> GetGlobals().SetNumber( " myvalue " ,? 123456 );

????
// ?获得Lua变量的值

???? int ?myvalue? = ?state -> GetGlobal( " myvalue " ).GetInteger();

????

????
// ?调用Lua函数

????LuaFunction < int > ?luaPrint? = ?state -> GetGlobal( " print " );

????luaPrint(
" Hello?Worldn " );

????

????
// ?让Lua调用C语言函数

???? int ?add( int ?a,? int ?b)

{?return?a+b;}

????state
-> GetGlobals().RegisterDirect( " add " ,?add);

????state
-> DoString( " print(add(3,4)) " );

????

????
// ?让Lua调用C++类成员函数

???? class ?Test

{public:?int?add(int?a,?int?b)

{return?a+b;}}
;

????Test?test;

????state
-> GetGlobals().RegisterDirect( " add " ,?test,?&Test::add);

????state
-> DoString( " print(add(3,4)) " );

???
3. 在Lua脚本中使用C++类
???
??? 这个稍微有点小麻烦。不过,我包装了一个LuaPlusHelper.h的文件,它可以很轻松的完成这个工作。它的实现也很简单,大家可以从源码上来获得如何用纯LuaPlus实现同样的功能。
??? 不过,这里仍然有一个限制没有解决:不能使用虚成员函数。不过考虑到我们仅是在Lua调用一下C++函数,并不是要将C++完美的导入到Lua,这个限制完全可以接受。
??? 另外,类成员变量不能直接在Lua中访问,可以通过类成员函数来访问(比如SetValue/GetValue之类)。?

// ?下面是一个简单的C++类:????

? class ?Logger

?

{

?
public:

??
void?LOGMEMBER(const?char*?message)

??

{

???printf(
"In?member?function:?%sn",?message);

??}

?

??Logger()

??

{

???printf(
"Constructing(%p)

n
",?this);

???v?
=?10;

??}

??
virtual?~Logger()

??

{

???printf(
"Destructing(%p)

n
",?this);

??}

?

??Logger(
int?n)

??

{

???printf(
"?--?Constructing[%d](%p)

n
",?n,?this);

??}

??Logger(Logger
*?logger)

??

{

???printf(
"?--?Constructing[%p](%p)

n
",?logger,?this);

???logger
->LOGMEMBER("?Call?From?Constructorn");

??}

??
int?SetValue(int?val)

??

{

???v?
=?val;

??}

??
int?GetValue()

??

{

???
return?v;

??}

?
public:

??
int?v;

?}
;

?

???? // ?导入到Lua脚本:

????LuaClass < Logger > (state)

???????.create(
" Logger " )? // ?定义构造函数?Logger::Logger()

???????.create < int > ( " Logger2 " )?? // ?定义构造函数?Logger::Logger(int)

???????.create < Logger *> ( " Logger3 " )? // ?定义构造函数?Logger::Logger(Logger*)

??????
?.destroy( " Free " )?? // ?定义析构函数?Logger::~Logger()

???????.destroy( " __gc " )?? // ?定义析构函数?Logger::~Logger()

???????.def( " lm " ,? & Logger::LOGMEMBER)?? // ?定义成员函数?Logger::LOGMEMBER(const?char*)

???????.def( " SetValue " ,? & Logger::SetValue)

???????.def(
" GetValue " ,? & Logger::GetValue);

?

???? // ?在Lua中使用Logger类(1):

????state -> DoString(

????????
" l?=?Logger(); " ?? // ?调用构造函数?Logger::Logger()

???????? " l:lm('Hello?World?1'); " ?? // ?调用成员函数?Logger::LOGMEMBER(const?char*)

???????? " l:Free(); " ?? // ?调用析构函数?Logger::~Logger()

????????);

?

???? // ?在Lua中使用Logger类(2):

????state -> DoString(

????????
" m?=?Logger2(10); " ? // ?调用构造函数?Logger::Logger(int)

???????? " m:lm('Hello?World?2'); " ?? // ?调用成员函数?Logger::LOGMEMBER(const?char*)

???????? " n?=?Logger3(m); " ? // ?调用构造函数?Logger::Logger(Logger*)

???????? " n:lm('Hello?World?3'); " ?? // ?调用成员函数?Logger::LOGMEMBER(const?char*)

???????? " m:SetValue(11); "

????????
" print(m.GetValue()); "

????????
" m,n?=?nil,?nil; " ? // ?m,n?将由Lua的垃极回收来调用析构函数

????????);


4. 将一组C函数归类到Lua模块

?

???? // 同上面一样,我采用LuaPlusHelper.h来简化:

????LuaModule(state,? " mymodule " )

???????.def(
" add " ,?add)

???????.def(
" add2 " ,?add);

?

????state
-> DoString(

????????
" print(mymodule.add(3,4)); "

????????
" print(mymodule.add2(3,4)); "

????????);


5. 使用Lua的Table数据类型

???? // ?在Lua中创建Table

????LuaObject?table? = ?state -> GetGlobals().CreateTable( " mytable " );

????table.SetInteger(
" m " ,? 10 );

????table.SetNumber(
" f " ,? 1.99 );

????table.SetString(
" s " ,? " Hello?World " );

????table.SetWString(
" ch " ,?L " 你好 " );

????table.SetString(
1 ,? " What " );

????

????
// ?相当于Lua中的:

????
// ?mytable?=?{m=10,?f=1.99,?s="Hello?World",?ch=L"你好",?"What"}

??

???? // ?也可以使用table作为key和value:

????state -> GetGlobals().CreateTable( " nexttable " )

????????.SetString(table,?
" Hello " )

????????.SetObject(
" obj " ,?table);

????
// ?相当于Lua中的:

????
// ?nexttable?=?{mytable="Hello",?obj=mytable}

?

???? // 获得Table的内容:

????LuaObject?t2? = ?state -> GetGlobals( " mytable " );

????
int ?m? = ?t2.GetByName( " m " ).GetInteger();

????

????LuaObject?t3?
= ?state -> GetGlobals( " nexttable " );

????std::
string ?str? = ?t3.GetByObject(t2).GetString();

???
6? 遍历Table

?

?LuaStateOwner?state;

?state.DoString(?
" MyTable?=?{?Hi?=?5,?Hello?=?10,?Yo?=?6?} " ?);

?

?LuaObject?obj?
= ?state.GetGlobals()[? " MyTable " ?];

?
for ?(?LuaTableIterator?it(?obj?);?it;?it.Next()?)

?

{

?????
const?char*?key?=?it.GetKey().GetString();

?????
int?num?=?it.GetValue().GetInteger();

?}


篇尾

上面我只是简单的举一些例子来说明LuaPlus以及LuaPlusHelper的使用方法,具体文档请参见LuaPlus。

需要下载LuaPlusHelper,请点这里:
http://files.cnblogs.com/ly4cn/LuaPlusHelper.rar

?

#pragma once

#include "luaplus.h"
#include <string>

class LuaConvert
{
public:
	LuaConvert(LuaObject& obj)
		: refobj(obj)
	{
	}
	operator int()
	{
		return refobj.GetInteger();
	}
	operator float()
	{
		return refobj.GetFloat();
	}
	operator double()
	{
		return refobj.GetDouble();
	}
	operator const char* ()
	{
		return refobj.GetString();
	}
	operator const wchar_t* ()
	{
		return refobj.GetWString();
	}
	operator std::string()
	{
		return std::string(refobj.GetString());
	}
	operator std::wstring()
	{
		return std::wstring(refobj.GetWString());
	}
	operator void* ()
	{
		return refobj.GetUserData();
	}
	template<typename T>
		operator T* ()
	{
		return (T*)refobj.GetUserData();
	}
	template<typename R>
		operator LuaFunction<R> ()
	{
		return LuaFunction<R>(refobj);
	}
private:
	LuaObject refobj;
};

template<typename Object>
class LuaConstructor
{
private:

	static	int ConstructorHelper(LuaState* state,Object* pObj)
	{
		std::string metaname("MetaClass_");
		metaname += typeid(Object).raw_name();

		LuaObject obj = state->BoxPointer(pObj);
		obj.SetMetaTable(state->GetGlobal(metaname.c_str()));
		obj.PushStack();
		return 1;
	}

public:

	static	int Constructor(LuaState* state)
	{
		return ConstructorHelper(state,new Object());
	}

	template<typename A1>
		static	int Constructor(LuaState* state)
	{
		LuaConvert a1 = LuaObject(state,1);
		return ConstructorHelper(state,new Object((A1)a1) );
	}

	template<typename A1,typename A2>
		static	int Constructor(LuaState* state)
	{
		LuaConvert a1 = LuaObject(state,1);
		LuaConvert a2 = LuaObject(state,2);
		return ConstructorHelper(state,new Object((A1)a1,(A2)a2) );
	}

	template<typename A1,typename A2,typename A3>
		static	int Constructor(LuaState* state)
	{
		LuaConvert a1 = LuaObject(state,2);
		LuaConvert a3 = LuaObject(state,3);
		return ConstructorHelper(state,(A2)a2,(A3)a3) );
	}

	template<typename A1,typename A3,typename A4>
		static	int Constructor(LuaState* state)
	{
		LuaConvert a1 = LuaObject(state,3);
		LuaConvert a4 = LuaObject(state,4);
		return ConstructorHelper(state,(A3)a3,(A4)a4) );
	}

	template<typename A1,typename A4,typename A5>
		static	int Constructor(LuaState* state)
	{
		LuaConvert a1 = LuaObject(state,4);
		LuaConvert a5 = LuaObject(state,5);
		return ConstructorHelper(state,(A4)a4,(A5)a5) );
	}

	static int Destructor(LuaState* state)
	{
		LuaObject o(state,1);

		delete (Object*)state->UnBoxPointer(1);

		LuaObject meta = state->GetGlobal("MetaClass_Nil");
		if(meta.IsNil())
		{
			meta = state->GetGlobals().CreateTable("MetaClass_Nil");
		}

		o.SetMetaTable(meta);
		return 0;
	}
};

template<typename Object>
class LuaClass
{
public:
	LuaClass(LuaState* state)
	{
		luaGlobals = state->GetGlobals();


		std::string metaname("MetaClass_");
		metaname += typeid(Object).raw_name();

		metaTableObj = luaGlobals.CreateTable(metaname.c_str());
		metaTableObj.SetObject("__index",metaTableObj);
		//metaTableObj.Register("__gc",&Destructor);
		//metaTableObj.Register("Free",&Destructor);
	}

	template<typename Func>
		inline LuaClass& def(const char* name,Func func)
	{
		metaTableObj.RegisterObjectDirect(name,(Object*) 0,func);
		return *this;
	}

	inline LuaClass& create(const char* name)
	{
		luaGlobals.Register(name,LuaConstructor<Object>::Constructor);
		return *this;
	}

	template<typename A1>
		inline LuaClass& create(const char* name)
	{
		luaGlobals.Register(name,LuaConstructor<Object>::Constructor<A1>);
		return *this;
	}
	template<typename A1,typename A2>
		inline LuaClass& create(const char* name)
	{
		luaGlobals.Register(name,LuaConstructor<Object>::Constructor<A1,A2>);
		return *this;
	}
	template<typename A1,typename A3>
		inline LuaClass& create(const char* name)
	{
		luaGlobals.Register(name,A2,A3>);
		return *this;
	}
	template<typename A1,typename A4>
		inline LuaClass& create(const char* name)
	{
		luaGlobals.Register(name,A3,A4>);
		return *this;
	}
	template<typename A1,typename A5>
		inline LuaClass& create(const char* name)
	{
		luaGlobals.Register(name,A4,A5>);
		return *this;
	}
	inline LuaClass& destroy(const char* name)
	{
		metaTableObj.Register(name,LuaConstructor<Object>::Destructor);
		return *this;
	}

private:
	LuaObject metaTableObj;
	LuaObject luaGlobals;
};

class LuaModule
{
public:
	LuaModule(LuaState* state)
	{
		luaModuleObj = state->GetGlobals();
	}

	LuaModule(LuaState* state,const char* name)
	{
		luaModuleObj = state->GetGlobals().CreateTable(name);
	}

	template<typename Func>
		inline LuaModule& def(const char* name,Func func)
	{
		luaModuleObj.RegisterDirect(name,func);
		return *this;
	}

	template<typename Object,typename Func>
		inline LuaModule& def(const char* name,Object& o,o,func);
		return *this;
	}

private:
	LuaObject luaModuleObj;
};




测试程序(VC7.1):
http://files.cnblogs.com/ly4cn/LuaPlusTest.rar

?

// LuaCppWrapper.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "LuaPlusHelper.h"

void LOG(const char* message)
{
	printf("In global function: %sn",message);
}

class Logger
{
public:
	void LOGMEMBER(const char* message)
	{
		printf("In member function: %sn",message);
	}

	virtual void LOGVIRTUAL(const char* message)
	{
		printf("In virtual member function: %sn",message);
	}

	Logger()
	{
		printf("Constructing(%p)...n",this);
		v = 10;
	}
	virtual ~Logger()
	{
		printf("Destructing(%p)...n",this);
	}

	Logger(int n)
	{
		printf(" -- Constructing[%d](%p)...n",n,this);
	}
	Logger(Logger* logger)
	{
		printf(" -- Constructing[%p](%p)...n",logger,this);
		logger->LOGMEMBER("-- 0000---0000n");
	}
public:
	int v;
};

void LOG2(const char* message,LuaObject xlogger)
{
	Logger* logger = (Logger*)xlogger.GetUserData();
	printf("In global function: %sn",message);
	printf("---%dn",logger->v);
	logger->LOGMEMBER(message);
}





int _tmain(int argc,_TCHAR* argv[])
{
	{
		LuaStateOwner state; 

		Logger logger;

		LuaModule(state)
			.def("LOG",LOG)
			.def("LOGMEMBER",&Logger::LOGMEMBER)
			.def("LOGVIRTUAL",&Logger::LOGVIRTUAL)
			.def("LOG2",LOG2);

		LuaClass<Logger>(state)
			.create("Logger")
			.create<int>("Logger2")
			.create<Logger*>("Logger3")
			.destroy("Free")
			.destroy("__gc")
			.def("lm",&Logger::LOGMEMBER)
			.def("lv",&Logger::LOGVIRTUAL);


		state->GetGlobals().SetNumber("a",123456);
		int a = state->GetGlobal("a").GetInteger();
		printf(" a = %dn",a);

		state->DoString("LOG('Hello')");
		state->DoString("LOGMEMBER('Hello')");
		state->DoString("LOGVIRTUAL('Hello')");

		state->DoString(
			"print('=========');"
			"print(Logger,_G['MetaClass_.?AVLogger@@']);"
			"l = Logger();"
			);
		state->DoString(
			"print(l);"
			"print(l.lv);"
			"print(l.lm);"
			);

		state->DoString("print('=========');");
		state->DoString("l:lm('Hhhhh');");
		//state->DoString("l:lv('Eeeee');"); //--虚函数不能用!!!
		state->DoString("--l:Free();l=nil;");

		state->DoString("print('=========');");
		state->DoString("LOG2('SSSS',l)");

		state->DoString("print('=========');");
		state->DoString("k = Logger2(10);k:lm('World2');k:Free();");

		state->DoString("print('=========',l);");
		state->DoString("h = Logger3(l);h:lm('World!!!!!!!!!');");

		LuaFunction<int> l = state->GetGlobal("LOG");
		l("DDDDDD");



	}

	system("Pause");
	return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读