Cocos 2 d-x TutorialのSocketの使用(2)


このセクションでは、C++バージョンのインタフェースをLuaに出力し、Luaでメッセージを送信および受信することを記録します.
一、cococos 2 dxを書くsocket_util.iniファイル
参考Cocos 2 d-x TutorialのC++クラスをLuaにバインドする方法
書き換え完了後の内容をここに貼り付けます
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
[cocos2dx_socket_util]
# the prefix to be added to the generated functions. You might or might not use this in your own
# templates
prefix = cocos2dx_socket_util

# 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 = 




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 -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/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 -U __SSE__

cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/external

cocos_flags = -DANDROID

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/../runtime-src/Classes/SocketUtil.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 = SocketUtil

# what should we skip? in the format ClassName::[function function]
# 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 = SocketUtil::[addMsgHandler addStateHandler addMsgHandlerLua addStateHandlerLua receiveMsg socketStateChange]






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 = 

# 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


二、genbindingsを書くsocket_util.pyファイルとバインドコードの生成
参考Cocos 2 d-x TutorialのC++クラスをLuaにバインドする方法
書き換え完了後の内容をここに貼り付けます
1
2
3
4
5
6
7
...
        output_dir = '%s/../runtime-src/Classes/auto' % project_root

        cmd_args = {
                    'cocos2dx_socket_util.ini' : ('cocos2dx_socket_util', 'lua_cocos2dx_socket_util_auto'), \
                    }
...

端末を開きgenbindingsに入りますsocket_util.pyが存在するディレクトリで、次のコマンドを実行してコードを生成します.
1
./genbindings_socket_util.py

エラーが報告されているかどうかを確認し、エラーが報告されていないことはコード生成に成功したことを示します.
三、特殊関数のバインドコードを書く
SocketUtilには2つの特殊な点の関数が含まれており、Luaから1つの関数の参照を渡す必要があり、C++に手動でバインドする必要があります.
Autoフォルダがあるディレクトリに新しいフォルダmanualを作成し、次のコードをコピーします.
lua_cocos2dx_socket_util_manual.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "base/ccConfig.h"
#ifndef __cocos2dx_socket_util_manual_h__
#define __cocos2dx_socket_util_manual_h__

#ifdef __cplusplus
extern "C" {
#endif
#include "tolua++.h"
#ifdef __cplusplus
}
#endif

int register_all_cocos2dx_socket_util_manual(lua_State* tolua_S);











#endif // __cocos2dx_socket_util_manual_h__

lua_cocos2dx_socket_util_manual.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "lua_cocos2dx_socket_util_manual.hpp"
#include "SocketUtil.h"
#include "tolua_fix.h"
#include "LuaBasicConversions.h"
#include "CCLuaValue.h"


int lua_cocos2dx_socket_util_SocketUtil_addStateHandlerLua(lua_State* tolua_S)
{
    int argc = 0;
    SocketUtil* cobj = nullptr;
    bool ok  = true;

#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
#endif


#if COCOS2D_DEBUG >= 1
    if (!tolua_isusertype(tolua_S,1,"SocketUtil",0,&tolua_err)) goto tolua_lerror;
#endif

    cobj = (SocketUtil*)tolua_tousertype(tolua_S,1,0);

#if COCOS2D_DEBUG >= 1
    if (!cobj)
    {
        tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_socket_util_SocketUtil_addStateHandlerLua'", nullptr);
        return 0;
    }
#endif

    argc = lua_gettop(tolua_S)-1;
    if (argc == 1)
    {
        LUA_FUNCTION arg0;
        do {
            arg0 = toluafix_ref_function(tolua_S,2,0);
        } while(0)
        ;
        if(!ok)
        {
            tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_socket_util_SocketUtil_addStateHandlerLua'", nullptr);
            return 0;
        }
        cobj->addStateHandlerLua(arg0);
        return 0;
    }
    luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d 
", "SocketUtil:addStateHandlerLua",argc, 1);
return 0; #if COCOS2D_DEBUG >= 1 tolua_lerror: tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_socket_util_SocketUtil_addStateHandlerLua'.",&tolua_err); #endif return 0; } int lua_cocos2dx_socket_util_SocketUtil_addMsgHandlerLua(lua_State* tolua_S) { int argc = 0; SocketUtil* cobj = nullptr; bool ok = true; #if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; #endif #if COCOS2D_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"SocketUtil",0,&tolua_err)) goto tolua_lerror; #endif cobj = (SocketUtil*)tolua_tousertype(tolua_S,1,0); #if COCOS2D_DEBUG >= 1 if (!cobj) { tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_socket_util_SocketUtil_addMsgHandlerLua'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; if (argc == 1) { LUA_FUNCTION arg0; do { arg0 = toluafix_ref_function(tolua_S,2,0); } while(0) ; if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_socket_util_SocketUtil_addMsgHandlerLua'", nullptr); return 0; } cobj->addMsgHandlerLua(arg0); return 0; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d
", "SocketUtil:addMsgHandlerLua",argc, 1);
return 0; #if COCOS2D_DEBUG >= 1 tolua_lerror: tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_socket_util_SocketUtil_addMsgHandlerLua'.",&tolua_err); #endif return 0; } int lua_register_cocos2dx_socket_util_SocketUtil_Manual(lua_State* tolua_S) { tolua_usertype(tolua_S,"SocketUtil"); tolua_cclass(tolua_S,"SocketUtil","SocketUtil","cc.Ref",nullptr); tolua_beginmodule(tolua_S,"SocketUtil"); tolua_function(tolua_S,"addStateHandlerLua",lua_cocos2dx_socket_util_SocketUtil_addStateHandlerLua); tolua_function(tolua_S,"addMsgHandlerLua",lua_cocos2dx_socket_util_SocketUtil_addMsgHandlerLua); tolua_endmodule(tolua_S); std::string typeName = typeid(SocketUtil).name(); g_luaType[typeName] = "SocketUtil"; g_typeCast["SocketUtil"] = "SocketUtil"; return 1; } TOLUA_API int register_all_cocos2dx_socket_util_manual(lua_State* tolua_S) { tolua_open(tolua_S); tolua_module(tolua_S,nullptr,0); tolua_beginmodule(tolua_S,nullptr); lua_register_cocos2dx_socket_util_SocketUtil_Manual(tolua_S); tolua_endmodule(tolua_S); return 1; }

四、バインド関数の登録
Classディレクトリの下のautoとmanualフォルダをプロジェクトに追加し、AppDelegateを変更します.cppファイル.
1
2
3
4
5
6
7
8
9
10
11
12
...
#include "lua_cocos2dx_socket_util_auto.hpp"
#include "lua_cocos2dx_socket_util_manual.hpp"
...
bool AppDelegate::applicationDidFinishLaunching()
{
    ...
    register_all_cocos2dx_socket_util(stack->getLuaState());
    register_all_cocos2dx_socket_util_manual(stack->getLuaState());
    ...
}
...

五、テスト
src/app/scenesの下にあるMainSceneを開きます.lua
テストコードの追加
MainScene.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function MainScene:ctor()
    ...
    local instance = SocketUtil:getInstance()
    instance:addMsgHandlerLua(handler(self, MainScene.msgHandler))
    instance:addStateHandlerLua(handler(self, MainScene.stateHandler))
    instance:connectServer("127.0.0.1", 3000)
    scheduler.performWithDelayGlobal(function(dt)
            local str = "hello world"
            instance:sendMsg({string.byte(str,1,#str)})
        end, 2)
    scheduler.performWithDelayGlobal(function(dt)
            instance:close()
        end, 4)
end

function MainScene:msgHandler(bytes)
    print("msg")
end

function MainScene:stateHandler(connected)
    print("state: "..tostring(connected))
end

サービス・エンド・プログラムの起動、実行、コンソール出力の確認
1
2
3
[LUA-print] state: true
[LUA-print] msg
[LUA-print] state: false

これでSocketUtilのLuaへのバインドが完了します.
–EOF–