cocos2d-x 3.0rc0 - bindings-generator 问题与解决

本想利用 cocos2d-x 自付的工具 bindings-generator 来将专案内的几个自写控件 binding 到 lua 下便于在 script 下控制,结果……真是他喵的坑啊…QAQ

cocos2d-x 3.0rc0 范例的 simple_test 的环境太单纯了,并且没有用到 cocos2d 内的任何物件,故!在撰写自己的 .ini 档时会遇上一狗票问题,于是要回头参考 tools/tolua 底下 cocos2d-x 本身的 lua binding 设定,这个说明能详细点吗? ~___~

把遇到的几个问题列一下,供大夥儿参考一下。

问题1:

于 Win7 或 Win8 环境下,如果自订的类别有参考到 cocos2d-x 类,写完自个儿的 .ini 档后俐落的直接执行,会在执行 .bat 后看到类似的错误:

Errors in parsing headers:

  1. <severity = Warning,

location = <SourceLocation file None, line 178, column 9>,

details = “‘WCHAR_MAX’ macro redefined”>

  1. <severity = Fatal,

location = <SourceLocation file ‘…/…/…/Evo/include/TalkWidgety.h’, line 38, column 10>,

details = “‘cocos2d.h’ file not found”>

好,这个很直觉,请在 .ini 设定档里加上 cocos2d-x headers 的路径。

于是,就近搬移
cocos2dx.ini 里对于 cocos2d-x 内路径的设定。当然,如果还有用到其他的如 ui 或是 cocostudio 的话,要一并移进来。

待会儿会在下头将完成的范例贴一下就会明白这儿在说些啥玩意。

问题2:

搬移完 cocos2d-x 等相关的 header 路径后心想这应该就搞定了吧?

BUT!天底下哪有这么便宜的事!

执行后赫然喵到下面的错误…… TAT

Errors in parsing headers:

  1. <severity = Warning,

location = <SourceLocation file None, line 179, column 9>, details = “‘WCHAR_MAX’ macro redefined”>

  1. <severity = Warning, location = <SourceLocation file ‘…/…/…/Evo/include/TalkWidgety.h’, line 27, column 9>,

details = ‘#pragma once in main file’>

  1. <severity = Fatal,

location = <SourceLocation file ‘D:…/…/…/cocos/base\CCConsole.h’, line 30, column 10>,

details = “‘BaseTsd.h’ file not found”>

惨!这下该怎么办……

花了点时间看了下产生 cocos2d-x 的
genbindings.py 才恍然大悟,原来要加上-U__MINGW32__ 的 undef 来避免问题。

原因?自己去看 CCConsole.h 的错误点就知道问题在哪了!这里不想多说,伤心啊!

解决以上两个问题的 .ini 如下,仅供参考:


prefix = evo_bindings

target_namespace = evo

cpp_namespace = Evo

自定义的变数,偷懒用

evo_root = …/…/…/…/Evo
evo_header = %(evo_root)s/include
cocosdir = …/…/…/

android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/include
android_flags = -D_SIZE_T_DEFINED_

clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include
clang_flags = -nostdinc -x c++ -std=c++11

从 cocos2dx.ini 等搬过来的

cocos_headers = -I%(cocosdir)s/cocos/2d -I%(cocosdir)s/cocos/ui -I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/physics -I%(cocosdir)s/cocos/2d/platform -I%(cocosdir)s/cocos/2d/platform/android -I%(cocosdir)s/cocos/math/kazmath -I%(cocosdir)s/extensions -I%(cocosdir)s/external -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s
cocos_flags = -DANDROID -U__MINGW32__

evo_headers = -I%(evo_root)s/include

extra_arguments = (android_headers)s (clang_headers)s (cocos_headers)s (evo_headers)s (android_flags)s (clang_flags)s (cocos_flags)s (extra_flags)s

headers = %(evo_header)s/TalkWidget.h
classes = TalkWidget

remove_prefix =
skip =
base_objects =
abstract_classes =
classes_have_type_info = no
rename =
rename_functions =
rename_classes =

classes for which there will be no “parent” lookup

classes_have_no_parents =

base classes which will be skipped when their sub-classes found them.

base_classes_to_skip =

Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are ‘yes’ or ‘no’.

script_control_cpp = no

问题3:

如果自定义的类别里有自行定义的 namespace 时,跑 .bat 后看 output log 的最后一行会发现这样的错误:

Exception: The namespace (Evo::TalkWidget) conversion wasn’t set in ‘ns_map’ section of the conversions.yaml

好吧,看错误内容……来去找一下
conversions.yaml 这个档,位置应该在
/tools/bindings-generator/targets/lua 底下,直接用文字编辑器打开来看。

我勒了个去!果然要把自订的 namespace 加到 ns_map 的变数中,那个 .ini 里的 cpp_namespace 作用果然只是用来卖萌的吧…=A=

要加的内容如下:


ns_map:

“cocos2d::extension::”: “cc.”

“cocos2d::ui::”: “ccui.”

“cocos2d::”: “cc.”

“spine::”: “sp.”

“cocostudio::”: “ccs.”

“cocosbuilder::”: “cc.”

“CocosDenshion::”: “cc.”

“Evo::”: “evo.”

问题4:

解决以上三个问题后,我的老天爷啊!很尴尬的是居然又遇上一个鸟问题,错误如下:

File …/…/tools/bindings-generator/evo/…/generator.py", line 220, in from_type

(ret_type, params) = r.groups()

AttributeError: ‘NoneType’ object has no attribute ‘groups’

……无言以对。

花了点时间看了下
generator.py 才发现,原来在
generator.py 的 line 219:

r = re.compile(‘function<(\S+) ((.*))>’).search(cdecl.displayname)

这里并没有考虑到会有人在类别里写
std::function<Object*()> 或
std::function<Object&()> 这样回传物件 pointer 或是 reference 的 functor,所以 regex 解析到坏掉。

也就是说,如果你的 code 里写了像这样的,请换个写法吧!

class TalkWidget : public cocos2d::ui::Widget

{

public:

bool setParseMethod(std::function<std::string&(const std::string&, const int)> &func);

};

如上面的 setParseMethod,func 是一个会回传 std::string reference (std::string&) 的 functor,这样子写就不行!

把整个 cocos2d-x 3.0rc0 找了遍……赫!果然整个 cocos2d-x 3.0rc0 里的 function functor 都是回传标准型别或干脆就是不回传任何玩意的 void。唉!真他喵的,踩到雷了……

由于不想多花时间去看整个
generator.py,所以,山不转路转,换个写法就好了。 =___=

c++11 functional 与 lambda function 参数自动绑定到 lua 中的任何解决方法,所以,问题四就直接无视吧!]

但是,麻烦有看到的大大请帮忙提醒一下要改正这个问题啊!这个是明显的 bug 而不是说明不详细了!

花了整整一下午才搞定,好累……看到这里,希望多少能提供点帮助给遇上一样问题的人。

以上!

你好,我是这么写的,为什么lua中不能直接使用
//MyScene.h
#ifndef MY_SCENE
#define MY_SCENE

class MyScene
{
public:

bool test();

};
#endif

//MyScene.cpp
#include “MyScene.h”

bool MyScene::test()
{
return 1;
}

//ini

the prefix to be added to the generated functions. You might or might not use this in your own

templates

prefix = cocos2dx_my

create a target namespace (in javascript, this would create some code like the equiv. to ns = ns || {})

all classes will be embedded in that namespace

target_namespace = cc

android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/include
android_flags = -D_SIZE_T_DEFINED_

clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include
clang_flags = -nostdinc -x c++ -std=c++11

cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/2d -I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/ui -I%(cocosdir)s/cocos/physics -I%(cocosdir)s/cocos/2d/platform -I%(cocosdir)s/cocos/2d/platform/android -I%(cocosdir)s/cocos/math/kazmath -I%(cocosdir)s/extensions -I%(cocosdir)s/external -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s

cocos_flags = -DANDROID -DCOCOS2D_JAVASCRIPT

cxxgenerator_headers =

extra arguments for clang

extra_arguments = (android_headers)s (clang_headers)s (cxxgenerator_headers)s (cocos_headers)s (android_flags)s (clang_flags)s (cocos_flags)s (extra_flags)s

what headers to parse

headers = %(cocosdir)s/cocos/my/MyScene.h

what classes to produce code for. You can use regular expressions here. When testing the regular

expression, it will be enclosed in “^", like this: "^Menu*”.

classes = MyScene.*

what should we skip? in the format ClassName::

ClassName is a regular expression, but will be used like this: “^ClassName$” functions are also

regular expressions, they will not be surrounded by “^$”. If you want to skip a whole class, just

add a single “" as functions. See bellow for several examples. A special class name is "”, which

will apply to all class names. This is a convenience wildcard to be able to skip similar named

functions from all classes.

skip =

rename_functions =

rename_classes =

for all class names, should we remove something when registering in the target VM?

remove_prefix =

classes for which there will be no “parent” lookup

classes_have_no_parents =

base classes which will be skipped when their sub-classes found them.

base_classes_to_skip =

classes that create no constructor

Set is special and we will use a hand-written constructor

abstract_classes = Skeleton SkeletonAnimation

Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are ‘yes’ or ‘no’.

script_control_cpp = no

//**.lua
lua中直接用:
local tt = MyScene:test()

嗯,有两个疑问:

一、由您的设置来臆测,被建置出来的 cocos2dx_my_bindings 中的 register_all_cocos2dx_my_bindings( ) 函数有挂到
LuaEngine 底下吗?

二、如果第一个问题回答是有的话,在 lua 底下应该也是无法直接使用。因为,MyScene 并没有被任何人建立起来,只是一个类但并不是物件实例。
而且在您的配置档里有加上:
target_namespace = cc,正确的写法应该是:

local tt = cc.MyScene.test()

但是这样执行的话会报错,會看到输出错误如下:

argument #1 is 'class cc.MyScene'; 'cc.MyScene' expected.

原因?因為沒有物件可供呼叫。故,您把 test( ) 函数改为 static 的话执行应该就没问题了。

以上。

感谢楼主的精彩分享!!!:801::801::801:

竟然漏过去了,已加入本周精华汇总~

http://www.cocoachina.com/bbs/read.php?tid=198321

问题已解决 太感谢啦!!

菜鸟请教一下:
class SpriteFactory
{
public:

enum  SpriteType  
{  
    en_close ,  
    en_grossini ,  
    en_grossinis_sister ,  
    en_grossinis_sister2
}; 
static SpriteFactory* sharedSpriteFactory();  

int createSprite(SpriteType enSpriteType);  

private:
static SpriteFactory* mFactory;
};
这个类我怎么转都不成功,好像和类中定义的枚举有关。不知道怎么解决?
ps:刚接触COCOS2DX和LUA,对于其中的含义目前完全不理解,纯粹按照网上的帖子教程在实现这个导出自定义类到lua.公司要求要搞这个,头发都急白了,求大神搭救!

好帖。。顶一个。。
我写了一个自己的框架,用了自己的命名空间,但是在调用lua_xxxxx_auto(engine->getLuaStack()->getLuaStack());的时候在tolua_module(tolua_S,“pf”,0); 这句里面的lua_getraw(L, -2); 总是报AccessViolation的错误。。不知道为什么。。

刚刚试了一下,无论是 3.0 rc0 或是最新的 final 版本,enumeration(原来这玩意在内地叫枚举,学习了……)的是否存在,并不会影响 toLua++ 的 binding code 自动生成。

他,只是近乎无视枚举而已。

枚举不会被产生出型别,仅是视为整数值,比较麻烦的是在 lua 中的调用与宣告。所以,应该是其他的问题造成的……

有错误讯息可以看吗?

呵呵,果然也中了一样的陷阱。

请打开 CCLuaEngine.cpp,位置在 cocos/scripting/lua-bindings/manual/ 底下。

找 LuaEngine::init( ) 函数:


bool LuaEngine::init(void)
{
_stack = LuaStack::create();
_stack->retain();
// executeScriptFile(“DeprecatedEnum.lua”);
// executeScriptFile(“DeprecatedClass.lua”);
// executeScriptFile(“Deprecated.lua”);
return true;
}

将三个执行 deprecated 用的 .lua 像上面一样的把他全部注解掉,让这个lua_State 维持清白之身。

然后在您的 AppDelegate.cpp 中挂载 module 后再来执行前面注解掉的三个 .lua。

唔,拿自带的 lua-tests 中的 AppDelegate.cpp 来做个范例:


// register lua engine
LuaEngine* pEngine = LuaEngine::getInstance();
ScriptEngineManager::getInstance()->setScriptEngine(pEngine);

#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID ||CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
LuaStack* stack = pEngine->getLuaStack();
register_assetsmanager_test_sample(stack->getLuaState());
#endif
executeScriptFile(“DeprecatedEnum.lua”);
executeScriptFile(“DeprecatedClass.lua”);
executeScriptFile(“Deprecated.lua”);

就这样,应当就很顺利的把您想 binding 的模组挂上去了。

这个是 cocos2d-x 3.0 的问题,而且是到了 final 版本都没修正。看来使用 3.0 + lua 开发的勇者们的数量极为稀少,应该都还是用那个有很好用的工具的 quick-cocos2d-x 吧……QAQ

什么?那为什么 lua-tests 也挂载了自己的玩意却不会挂掉?


int register_assetsmanager_test_sample(lua_State* L)
{
tolua_open(L);
tolua_module(L, NULL, 0);
tolua_beginmodule(L, NULL);
tolua_function(L, “createDownloadDir”, lua_cocos2dx_createDownloadDir);
tolua_function(L, “deleteDownloadDir”, lua_cocos2dx_deleteDownloadDir);
tolua_function(L, “addSearchPath”, lua_cocos2dx_addSearchPath);
tolua_endmodule(L);
return 0;
}

如上……他挂的是 functions 而不是整套 module。不信?可以试试把 tolua_module( ) 的 NULL 填上名字,一执行……也是出现一样的错误哩!

以上。

Ps. 论坛内的代码高亮是坏的吧……T___T

感谢解答!那个问题解决了,不是定义的问题,原来在ini文件中这一句:
android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/u sr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/include
俺电脑里只有4.6和4.8,改成4.8就没问题了。。。

蛋疼,我跑 genbindings.py 也是遇到一样问题。谢谢lz

我也遇到这么个问题,但按照这方法并没有解决呢~ 还提示找不到或未加载lua51.dll。请问你们是这种情况么

感谢楼主分享。。终于解决了找不到文件的问题。

我这里全都是警告,没有Error,但是最后还是build failed,请问楼主有碰到过么?

Errors in parsing headers:

  1. <severity = Warning,
    location = <SourceLocation file None, line 179, column 9>,
    details = “‘WCHAR_MAX’ macro redefined”>
  2. <severity = Warning,
    location = <SourceLocation file ‘d:\ProgramFiles\android-ndk-r9d\toolchai
    ns\llvm-3.3\prebuilt\windows-x86_64/lib/clang/3.3/include\float.h’, line 86,
    column 9>,
    details = “‘FLT_DIG’ macro redefined”>
  3. <severity = Warning,
    location = <SourceLocation file ‘d:\ProgramFiles\android-ndk-r9d\toolchai
    ns\llvm-3.3\prebuilt\windows-x86_64/lib/clang/3.3/include\float.h’, line 87,
    column 9>,
    details = “‘DBL_DIG’ macro redefined”>
  4. <severity = Warning,
    location = <SourceLocation file ‘d:\ProgramFiles\android-ndk-r9d\toolchai
    ns\llvm-3.3\prebuilt\windows-x86_64/lib/clang/3.3/include\float.h’, line 106
    , column 9>,
    details = “‘FLT_MAX’ macro redefined”>
  5. <severity = Warning,
    location = <SourceLocation file ‘d:\ProgramFiles\android-ndk-r9d\toolchai
    ns\llvm-3.3\prebuilt\windows-x86_64/lib/clang/3.3/include\float.h’, line 107
    , column 9>,
    details = “‘DBL_MAX’ macro redefined”>
  6. <severity = Warning,
    location = <SourceLocation file ‘d:\ProgramFiles\android-ndk-r9d\toolchai
    ns\llvm-3.3\prebuilt\windows-x86_64/lib/clang/3.3/include\float.h’, line 114
    , column 9>,
    details = “‘FLT_MIN’ macro redefined”>
  7. <severity = Warning,
    location = <SourceLocation file ‘d:\ProgramFiles\android-ndk-r9d\toolchai
    ns\llvm-3.3\prebuilt\windows-x86_64/lib/clang/3.3/include\float.h’, line 115
    , column 9>,
    details = “‘DBL_MIN’ macro redefined”>
    ====

dos2unix: converting file api to UNIX format …
dos2unix: problems converting file api

Generating lua bindings fails.

:14: :14: :14: :14: :14: :14: :14: