游戏开发论坛

 找回密码
 立即注册
搜索
查看: 8003|回复: 18

自制 lua C_API 的 c++封装

[复制链接]

6

主题

95

帖子

103

积分

注册会员

Rank: 2

积分
103
发表于 2006-9-21 08:52:00 | 显示全部楼层 |阅读模式
自己封装了一套lua的c++封装库(5.1),优点是上手极容易,而且只有头文件(pure-.h),易于安装,可在vc8下编译通过。现在发一个示例:





//CPP
#include <iostream>

#include ".\DxLua.h"//唯一需要include的头文件

using namespace std;

namespace Test{
struct test_t
{
  int n;
  const test_t* ft(test_t& r){cout<<"f(test_t* r)\n";r.n = 55;return this;}
};
}

//完成c++类到lua的映射,在任意cpp文件内定义一次即可(不可重复定义)
BEGIN_CLASS2LUA(::Test::test_t)
LUA_METHOD(ft)
END_CLASS2LUA

void my_print(int v)
{
  cout<<"my_print:"<<v<<endl;
};

int __cdecl main()
{
  using namespace Dx;
  using namespace Dx:ua;

  try{
    Domain d;

    d.global["print"] = FUN2LUA(my_print);//可以替换库自带的print,FUN2LUA是宏

    d.LoadFile("Test.lua");

    Test::test_t t1 = {0},t2 = {0};
    Reference run_host(d.global["run_host"]);//Reference类指向任意lua对象

    run_host(UDT(t1),UDT(t2));//用户自定义类型用UDT作wrap
    cout<<t2.n<<endl;

    d += "run_host = function(t1,t2)t2:ft(t1) print(888) end";

    run_host = d.global["run_host"];
    run_host(UDT(t2),UDT(t1));

    for(TableRange<> rg(d.global["the_table"]);rg;++rg)//TableRange 作用相当于 iterator 用于遍历一个表
    {
      string k;
      Set(k) = rg.key;//从lua中读取变量
      cout<<k<<" : "<<(*rg).TypeName()<<endl;
    }

    string tmp;
    Set(tmp) = d.global["the_name"];
    cout<<tmp<<endl;
    Set(tmp) = d.global["the_table"]["name"];
    cout<<tmp<<endl;
    Set(tmp) = d.global["the_table"]["get_name"]("left","right");
    cout<<tmp<<endl;
    Reference newtb(d.global["make_table"]());
    Set(tmp) = (newtb->*newtb["fun"])();// = newtb:f();
    cout<<tmp<<endl;
  }
  catch(Lua::ScriptError& e)
  {
    cerr<<"\n!!!catch a scrpt error:\n"<<e.what();
  }
return 0;
}

//Test.lua
the_table = {
[1] = {},
name = "Eri",
fun = function(t)
t.name = t.name.."Sch"
end,

sub_table =
{
name = "Iori"
},
get_name = function(str1,str2)
return str1.." + "..str2
end,
get_pair = function(str1,str2)
return str1.." 1+ "..str2,str2.." 2+ "..str1
end,
name_test = "NaNi",
number_test = 54.6
}

the_name = "Slash"

function make_table()
t =
{
name = " as it ",
fun = function(o)
o.name = o.name.." + "
return o.name
end
}
return t
end

function run_host(t1,t2)

t = t1:ft(t2)
t:ft(t1)
end

输出
f(test_t* r)
f(test_t* r)
55
f(test_t* r)
my_print:888
number_test : number
: table
name : string
get_pair : function
name_test : string
get_name : function
sub_table : table
fun : function
Slash
Eri
left + right
as it  +

我看过不少库,最完善的属配boost的lua-bind,但是其太笨重。该库的大部分功能本库都有,而且本库轻巧的多。
目前,国内的封装,厚着脸说,我还没见到更好的,如果哪位见到国内更胜于此的,请告诉我,以便见贤思齐。另外如果对此有兴趣的人多,我会把全部代码放出来的。

本库还有改进余地,若各位有其他期待请大胆提出。

(ACGFan = qslash)
[em20]

7

主题

61

帖子

61

积分

注册会员

Rank: 2

积分
61
发表于 2006-9-21 10:31:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装

自制封装LUA类也比较简单一个40行左右的头文件,不过功能也简单
C++中的函数
void CMainGame::Warning(char *str)
{
        MessageBox(NULL,str,"Error",0);
}
注册进lua中,m_MainGame是CMainGame的指针
m_Script->AddFunction("Warning",m_MainGame,&CMainGame::Warning);

lua中就可以调用Warning函数了

6

主题

95

帖子

103

积分

注册会员

Rank: 2

积分
103
 楼主| 发表于 2006-9-21 16:57:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装


我的是这样的:

BEGIN_CLASS2LUA(::Test::test_t)
LUA_METHOD(ft)
END_CLASS2LUA

如果没有定义映射而传入UDT类型引用,则不能通过连接。一旦定义,不用手动注册,会在第一次传入数据时自动注册,并对传入的userdata调用lua_setmetatable。我觉得这样能省心不少。

6

主题

95

帖子

103

积分

注册会员

Rank: 2

积分
103
 楼主| 发表于 2006-9-21 17:00:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装


如果是非成员函数,如此定义:d.global["print"] = FUN2LUA(my_print)

#define FUN2LUA(...) :x:ua::FunWrapImpl::GetFunctionWraper(__VA_ARGS__).get<__VA_ARGS__>()
#define BEGIN_CLASS2LUA(...) namespace Dx{namespace Lua{  template<>RegisterInfo HostRegistryInfo<__VA_ARGS__>(){  static char className[] = #__VA_ARGS__;  typedef __VA_ARGS__ type;  static bool first = true;  if(first){    for(char* s = className; *s != '\0'; ++s)      if( *s == ':' || *s == '<' || *s == '>' || *s == ',' )        *s = '_';    first = false;  }  static luaL_Reg lib[] = {


#define END_CLASS2LUA  ,{0}};  RegisterInfo res = {className,lib}; return res;}}}

#define LUA_METHOD(method) {#method,FUN2LUA(&type::method)}

6

主题

95

帖子

103

积分

注册会员

Rank: 2

积分
103
 楼主| 发表于 2006-9-21 18:19:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装

FUN2LUA 返回的是lua_CFunction。该库未曾使用lua_newuserdata。

6

主题

95

帖子

103

积分

注册会员

Rank: 2

积分
103
 楼主| 发表于 2006-9-21 18:24:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装

猜测一下,逆火十三先生用的方法,是设置了userdata的metatable中的__call。
我目前就见过这种方法,和我用的那种。(用模板生成lua_CFunction)。

7

主题

61

帖子

61

积分

注册会员

Rank: 2

积分
61
发表于 2006-9-22 09:09:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装

我不过是把类和成员函数指针记录下来,调用的时候用汇编实现

6

主题

95

帖子

103

积分

注册会员

Rank: 2

积分
103
 楼主| 发表于 2006-9-22 10:48:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装

比如:
Warning();
在lua一端调用的,是userdata吧。

Warning应该只能是userdata,table,或lua_CFunction。
应该是lua_newuserdata分配空间,然后存储类和成员函数指针吧?

16

主题

160

帖子

176

积分

注册会员

Rank: 2

积分
176
QQ
发表于 2006-9-25 15:16:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装

使用boost/bind是笨重了些,但是也方便多了,还是推荐使用LuaWrap。
楼主贴了一大堆代码,却没有提供源代码,太不厚道了=_=

6

主题

95

帖子

103

积分

注册会员

Rank: 2

积分
103
 楼主| 发表于 2006-9-27 12:05:00 | 显示全部楼层

Re:自制 lua C_API 的 c++封装

抱歉,文档还没写,代码注释太少,怕大家看着窝心,怎么传附件?
这是源码。vc7.0没戏,8.0保证,7.1没试过。
DxLua.zip:http://pickup.mofile.com/0360324032643102
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 12:42

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表