战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

 

最近准备在手机项目客户端中使用lua, 以前一直在服务器使用luabind. 另外, tolua++也体验过, LuaPlus也在早年用过. 以下是本人对这些绑定库的个人感觉:

luabind

利用boost机制把绑定做到极致, 比较适合主c++, 弱lua的脚本框架.

作者已经停止更新, 在windows/linux编译没问题, 但是在ios的LLVM下, 无法编译

tolua++

像cocos2dx使用tolua++也是可以理解的, 那么多函数需要绑定, tolua++的头文件parse及自动代码生成节约了很多手动绑定的时间.

但是看到代码中有一部分bugfix就心存不安(纯个人感觉, 本人使用不多, 欢迎砖头伺候),另外, tolua++只能由脚本层驱动C++, 而没有将已经实例化的句柄注册到lua的功能也是煞笔啊

 

LuaPlus

接口较为简单, 适于初学者上手, 无任何的模板, 性能不高

 

luaBridge

项目地址: https://github.com/vinniefalco/LuaBridge

手册: http://vinniefalco.com/LuaBridge/Manual.html

纯头文件实现, 无需编译, 包含进入工程即可, 接口简洁高效

相比luabind, 唯一不能实现的常用功能就是枚举, 但是可以支持类成员静态变量注册, 这个就无所谓了, 手写一个枚举支持也很简单

看下演示代码:

class A
{
public:
    A( )
    {

    }
    virtual void foo( int a )
    {
        printf("foo base\n");
    }

    std::string Member;
};

class B : public A
{
public:
    virtual void foo( int a )
    {
        printf("foo inherited\n");
    }
};
void foo( int b )
{

}

luabridge::getGlobalNamespace(L)
        .beginClass<A>("Sobj")
            .addConstructor<void (*) (void)> ()
            .addFunction("foo", &A::foo)
            .addData("Member",&A::Member)
        .endClass()
        .deriveClass<B, A>("SSec")
            .addFunction("foo",&B::foo )
        .endClass();

    luabridge::getGlobalNamespace(L).addFunction("foo", foo );


    B ins;
    ins.Member = "data";
    luabridge::setGlobal(L, ins, "ins");

lua侧的代码

local a = Sobj()
a:foo(2)
a.Member = "hello"


ins:foo(3)
posted on 2013-12-07 14:05 战魂小筑 阅读(12220) 评论(24)  编辑 收藏 引用 所属分类: 脚本技术C++/ 编程语言

评论

# re: 超越luabind的luaBridge[未登录] 2013-12-08 22:44 微妙的平衡
这个不错  回复  更多评论
  

# re: 超越luabind的luaBridge 2013-12-09 00:26 杨粼波
我用过的棒子货LuaTinker倒是不错.
这个可以尝试下...  回复  更多评论
  

# re: 超越luabind的luaBridge 2013-12-09 09:47 战魂小筑
我也用过, 但是用过luabridge后, 那货也就放箱底了@杨粼波
  回复  更多评论
  

# re: 超越luabind的luaBridge 2013-12-13 17:38 力为
还在用luabind。
貌似有人继续维护吧?  回复  更多评论
  

# re: 超越luabind的luaBridge 2014-01-03 21:44 战魂小筑
开源的,自己改也没问题。况且这段时间用下来没啥问题@力为
  回复  更多评论
  

# re: 超越luabind的luaBridge 2014-03-13 16:20 sthouwu
哈哈,之前端游项目就是用的LuaBridge。  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 09:26 phantom
luabridge绑定的成员函数,如果参数个数大于1个,从脚本调用直接就crash,你没有遇到这个问题?  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 09:29 phantom
我就是看你这个博客才用的luabridge,结果一试,这个问题太明显,而且更妙的是,官方demo没有一个超过2参的例子,不得不承认这库真是太傻逼了。  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 09:31 战魂小筑
@phantom
我用的非常正常, 没发现有什么问题
1. 没改源码
2. 都参考官方例子使用
碰到问题, 贴出代码来才是王道, 人家也是测了很久才发的
发现问题就骂库, 绕半天才发现是自己的问题  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 13:19 phantom
@战魂小筑
谢谢你回复这么快,我传到百度盘了,代码很少
http://pan.baidu.com/s/1c0c62ru
owcmn.h忘了打包给个github地址
https://github.com/bhlzlx/graphics/blob/master/ow/owcmn/owcmn.h
别外,我直接下载的luabridge最新版,有编译错误,pushstring的地方要改成pushlstring才编译过去。
所以我才好烦啊,写个库最基本的都有问题感觉,所以才来请教大神,有没有遇到这样的问题。  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 13:27 战魂小筑
@phantom
调用lua用luabridge也就是一句话, 干嘛写个scriptengine又封装一层...
你把官方的例子照着跑一遍, 别封装了, 速度慢不说, 经常搞出的错误全是自己搞的

代码能否搞个直接可以编译的, 给你看代码比开源代码都麻烦, 无法编译  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 13:36 phantom
注册的代码在这
.beginClass<ow::MemBuffer>( "MemBuffer" )
.addFunction( "Size", &ow::MemBuffer::Size )
.addFunction( "Seek", &ow::MemBuffer::Seek )
.addFunction( "Read", &ow::MemBuffer::Read )
.addFunction<owINT32 (ow::MemBuffer::*)( const owVOID*,owINT32 )>( "Write", &ow::MemBuffer::Write )
.addFunction( "Resize", &ow::MemBuffer::Resize )
.addFunction( "Eof", &ow::MemBuffer::Eof )
.addFunction( "GetCurr", &ow::MemBuffer::GetCurr )
.addFunction( "GetBuffer", &ow::MemBuffer::GetBuffer )
.addFunction( "Release", &ow::MemBuffer::Release )
.endClass()
MemBuffer的定义在buffer.h里,单独测试一下这个write方法就好。  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 13:42 phantom
我这是用codelite + gcc写的,要不我做一个vs2010的工程给你看。  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 13:55 phantom
vs2010下载下来直接就可以编译,宏我也展开了,方便你看,在init方法里。
http://pan.baidu.com/s/1jGGpPYI  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 14:00 战魂小筑
@phantom
engine.CallVoidScript("script_MemBufferWrite",pBuff,(void*)&size,sizeof(int));

你的(void*)&size想表达什么意思? 穿大小就把size传进去, lua不支持指针!  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 14:06 phantom
@战魂小筑
因为那是个数据起始地址,我就随便往buffer里写4个字节数据,就所以就随便取了一个size变量的地址,传进去size的大小。假设我在lua里调,buffer:Write("Hello,World!",12)也会崩。这正常吗?  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 14:07 战魂小筑
@phantom
lua不能这么玩, 你先查下资料吧, 脚本没指针, 无法操作内存,只有常用类型  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-10-28 14:27 phantom
果然是这样,我又加了个不带指针的多参方法,没有此问题了,我去补一下lua相关知识。非常感谢~  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-11-05 17:52 hcaihao
LuaBridge不支持下面特性:
枚举型常量
不支持8个以上的函数或方法的调用
重载函数、方法和构造函数(Overloaded functions, methods, or constructors)
全局变量(变量必须被包装在命名空间里)
自动地转换STL容器类型和Table
在Lua中继承C++类(Inheriting Lua classes from C++ classes)。
Passing nil to a C++ function that expects a pointer or reference
Standard containers like std::shared_ptr   回复  更多评论
  

# re: 超越luabind的luaBridge 2015-12-03 15:25 super_huai
@战魂小筑
试用了一下,感觉不错。但是有wchar_t* 参数的函数一直注册不上,不知道什么原因
void foo( const wchar_t* str )
{
}
luabridge::getGlobalNamespace(L).addFunction("foo", foo );

lua侧的代码

foo("123"); //崩溃了

不知道有什么方法可以解决?  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-12-03 15:26 战魂小筑
@super_huai
除非你注定主做windows, 否则还是全用char+utf8吧
wchar的东西很烦的  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-12-03 16:03 super_huai
@战魂小筑
感谢回复
看了luaBridge的说明,是可以做到支持的
## The Lua Stack

In the Lua C API, all operations on the `lua_State` are performed through the
Lua stack. In order to pass parameters back and forth between C++ and Lua,
LuaBridge uses specializations of this template class concept:

template <class T>
struct Stack
{
static void push (lua_State* L, T t);
static T get (lua_State* L, int index);
};

The Stack template class specializations are used automatically for variables,
properties, data members, property members, function arguments and return
values. These basic types are supported:

- `bool`
- `char`, converted to a string of length one.
- `char const*` and `std::string` strings.
- Integers, `float`, and `double`, converted to `Lua_number`.

User-defined types which are convertible to one of the basic types are
possible, simply provide a `Stack <>` specialization in the `luabridge`
namespace for your user-defined type, modeled after the existing types.
For example, here is a specialization for a [juce::String][6]:

template <>
struct Stack <juce::String>
{
static void push (lua_State* L, juce::String s)
{
lua_pushstring (L, s.toUTF8 ());
}

static juce::String get (lua_State* L, int index)
{
return juce::String (luaL_checkstring (L, index));
}
};  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-12-03 16:04 战魂小筑
@super_huai
真心建议别这样, 太慢了, 转来转去的  回复  更多评论
  

# re: 超越luabind的luaBridge 2015-12-03 16:13 super_huai
@战魂小筑
因为是从现有的库做的,该库操作的全是unicode,全部改造代价太大,所以不得不这么转
现在实现的方式如下
c++
int Utf8ToT(lua_State *L)
{
size_t n = 0;
char* str = (char*)luaL_checklstring(L, -1, &n);
if(!str) return 0;
tstring strT=UTF82W(str);
lua_pushlstring(L, (const char*)(LPCWSTR)strT.c_str(), (strT.size()+1)*sizeof(wchar_t));
return 1;
}

luabridge::getGlobalNamespace(L)
.addCFunction("A2T", Utf8ToT );

luaL_dostring(L,"function T (str)\n return A2T(str);\nend");//注册一个全局的"T"函数,用来将utf8编码的字符串转换为TCHAR

lua侧的代码

foo(T"123");   回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理