9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Cocos2d-xAdvent Calendar 2014

Day 4

【Cocos2d-x】Script Bindingの作り方(その2)

Last updated at Posted at 2014-12-04

その1の続きです
【Cocos2d-x】Script Bindingの作り方(その1)

それではbindings-generatorの実装方法を説明します。

#Lang言語用のファイルを作る
まずはCococ2d-xのtoolsディレクトリ配下で、Lang言語用のディレクトリを作成します。
一から作るのは大変なので、Luaのディレクトリをコピーすることにします。

cp -r tools/tolua tools/lang
cp -r tools/bindings-generator/targets/lua tools/bindings-generator/targets/lang

まずはtools/langディレクトリのファイルを見てみましょう。
genbindings.pyというPythonスクリプトと、"cocos2dx"で始まるiniファイルがいくつかあるかと思います。

genbindings.pyを開き、try〜except句の以下の部分を書き換えます。

  • tolua / luaとなっているのをlangに変更
  • cmd_argsの中身を一旦"cocos2d-x.ini"のみにする
try:

    lang_root = '%s/tools/lang' % project_root
    output_dir = '%s/cocos/scripting/lang-bindings/auto' % project_root

    cmd_args = {'cocos2dx.ini' : ('cocos2d-x', 'lang_cocos2dx_auto'), \
                }
    target = 'lang'
    generator_py = '%s/generator.py' % cxx_generator_root
    for key in cmd_args.keys():
        args = cmd_args[key]
        cfg = '%s/%s' % (lang_root, key)
        print 'Generating bindings for %s...' % (key[:-4])
        command = '%s %s %s -s %s -t %s -o %s -n %s' % (python_bin, generator_py, cfg, args[0], target, output_dir, args[1])
        _run_cmd(command)

    if platform == 'win32':
        with _pushd(output_dir):
            _run_cmd('dos2unix *')

    print '---------------------------------'
    print 'Generating lang bindings succeeds.'
    print '---------------------------------'

except Exception as e:
    if e.__class__.__name__ == 'CmdError':
        print '---------------------------------'
        print 'Generating lang bindings fails.'
        print '---------------------------------'
        sys.exit(1)
    else:
        raise

こんな感じになります。

cmd_argsには生成する対象のソースとその設定ファイルを記述します。
最初から全てに対応するのは難しいので、まずは一番基本となる"cocos2d-x.ini"だけに限定しています。
"cocos2d-x.ini"が完璧になったところで、対応ファイルを1つずつ増やしていくと良いと思います。

次に、"cocos2d-x.ini"の中身を見てみましょう。
色々と設定がありますが、書き換えることがありそうな項目は以下のあたりだと思います。

  • headers

解析する対象のC++のヘッダ。指定したヘッダファイルを起点にincludeを辿って解析していく。

  • classes

生成対象のクラス。

  • skip

classesで指定したクラスの中で、除外するメソッドを記載。
例えば Sprite::[getQuad] は、SpriteクラスのgetQuadメソッドは除外するということ。
[*]は、全てのメソッドということ。

  • rename_functions

Lang言語上に作るメソッド名を、C++のメソッド名と異なるものにする場合に指定。
やたら長いメソッド名を短くしたりする。

  • rename_classes

Lang言語上に作るクラス名を、C++のメソッド名と異なるものにする場合に指定。

  • abstract_classes

抽象クラスを指定。(コンストクタを作らない)

iniファイルの中身を確認したら、一旦何も変更せずに閉じてください。

それではこの状態でbindings-generatorを実行し、グルーコードを生成してみましょう。
先ほど書き換えたgenbindings.pyを実行してください。
いくつかログが出た後に、"Generating lang bindings succeeds." と表示されれば成功です。
成功した場合、以下のファイルが生成されているはずです。

cocos2d-x/cocos/scripting/lang-bindings/auto/lang_cocos2dx_auto.hpp
cocos2d-x/cocos/scripting/lang-bindings/auto/lang_cocos2dx_auto.cpp

生成コードはまだ何も変更していないので、中身はLua用の記述のままになってます。

#グルーコード生成用のテンプレートファイルを編集
生成されるコードを変更するには以下のディレクトリ配下にある、テンプレートファイルを変更します。
なお、bindings-generatorはCheetahというPythonのテンプレートエンジンを使用しているため、
Cheetahの文法に従って書いていくことになります。

cocos2d-x/tools/bindings-generator/targets/lang/templates/

templatesディレクトリの下には以下のテンプレートファイルがあります。

  • layout_head.h

生成される.hppファイルの先頭に出力される。#include等を書く。
register_all_cocos2dx関数のプロトタイプをここで書いておく。

  • layout_head.c

生成される.cppファイルの先頭に出力される。#include等を書く。

  • layout_foot.h

生成される.hppファイルの末尾に出力される。

  • layout_foot.c

生成される.cppファイルの末尾に出力される。register_all_cocos2dx関数を実装し、
各クラス毎に定義したregisterメソッドを呼び出す処理を書く。

  • prelude.h

各クラス毎のまとまりの最初に出力される。

  • prelude.c

各クラス毎のまとまりの最初に出力される。クラス毎に生成したいコードがあれば書く。

  • register.c

lang_register_cocos2dx_*関数を実装する。クラス毎にbinding登録関数をまとめたもの。

  • ifunction.c

メンバ関数毎に出力される。

  • ifunction_overloaded.c

メンバ関数毎に出力される。オーバーロードしている場合はこちらが出力される。

  • sfunction.c

静的メンバ関数毎に出力される。

  • sfunction_overloaded.c

静的メンバ関数毎に出力される。オーバーロードしている場合はこちらが出力される。

  • lambda.c

std::functionをbindingする際に出力される。

  • function.h

メンバ関数毎に.hppファイルで出力される。(function.c共通のファイル)

関数をオーバーロードしている場合は別ファイルになっていますが、これはオーバーロードしている場合は
Lang言語から渡された引数の数や型で、どのオーバーロード関数を実行するかを判定する必要があり、
処理が複雑になるためです。
また、apidoc_*というテンプレートがあるかと思いますが、これはapidoc用に
Lang言語上に生成される関数のシグネチャをコメントで出力するためのものです。

テンプレート関連で、もう一つ以下のYamlファイルを編集する必要があります。
cocos2d-x/tools/bindings-generator/targets/lang/conversions.yaml

中身を見るとなんとなくわかるかと思いますが、型の変換方法を定義しているファイルです。
C++⇔Lang言語間の型変換関数を使って、型ごとに呼び出す変換関数を定義します。
"to_native"は、Lang言語 -> C++、from_nativeはその逆です。
なお、キーの文字列で、"@"で始まるものがいくつかあると思いますが、"@"で始まる文字列は正規表現として扱います。

#generator.pyを編集
C++のコードを解析しながら、テンプレートを使ってコードを出力していくのがgenerator.pyです。
つまり、bindings-generatorの本体のスクリプトとなります。
テンプレートの修正だけでは足りない場合等は、generator.pyを直接いじることになります。

なお、C++コードの解析には以下のスクリプトを使っています。
cocos2d-x/tools/bindings-generator/clang/cindex.py
これはClangのPython bindingで、Clangのソースコードに付属しているものです。

#最後に
説明が足りないところも多いかとは思いますが、とりあえずここまでです。
cocosコマンドの対応については私自身現在実装しているところだったりするので、
ある程度まとまったら(その3)として書くかもしれません。
私は現在Squirrelという言語のbindingを少しずつ作っているところです。

明日のAdvent Calendarは、giginetさんです。
giginetさんは12/24にCocos2d-x本を出版されるそうです。おめでとうございます!
私は既にAmazonで予約しました。

以上です。
(書いている間に12月4日が終わっていました。ごめんなさい...)

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?