Cocos2d-x手动绑定C++类到Lua .

作者:glory 首发泰然,转发请注明出处。

Cocos2d-x 3.0开始, Lua Binding使用tolua++方式自动绑定底层C++类到Lua层,使用户能够用Lua方式调用引擎各种接口。但是用户还是希望手动绑定某些自定义类,所以接下来的内容将一步一步讲解如何手动将自定义C++类绑定到Lua。

创建自定义类

首先,定义一个类Foo,这个类就是接下来要绑定到Lua的类。

注意:所有C++类文件必须放在 Classes 文件夹里,所有Lua文件必须放在 Resources 文件夹里。

在 fun.h 头文件中添加如下代码:

<span class="com" style="color:#aeaeae;FONT-STYLE: italic;">#include</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;"><iostream></span><span class="pln" style="color:#ffffff;">
</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">#include</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;"><sstream></span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">class</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">public</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;">
    </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pun" style="color:#ffffff;">(</span><span class="kwd" style="color:#e28964;">const</span><span class="pln" style="color:#ffffff;"> std</span><span class="pun" style="color:#ffffff;">::</span><span class="kwd" style="color:#e28964;">string</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">&</span><span class="pln" style="color:#ffffff;"> name</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;"> name</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">name</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
    </span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
        std</span><span class="pun" style="color:#ffffff;">::</span><span class="pln" style="color:#ffffff;">cout </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"Foo is born"</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> std</span><span class="pun" style="color:#ffffff;">::</span><span class="pln" style="color:#ffffff;">endl</span><span class="pun" style="color:#ffffff;">;</span><span class="pln" style="color:#ffffff;">
    </span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">
    
    std</span><span class="pun" style="color:#ffffff;">::</span><span class="kwd" style="color:#e28964;">string</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">Add</span><span class="pun" style="color:#ffffff;">(</span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> a</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> b</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
    </span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
        std</span><span class="pun" style="color:#ffffff;">::</span><span class="pln" style="color:#ffffff;">stringstream ss</span><span class="pun" style="color:#ffffff;">;</span><span class="pln" style="color:#ffffff;">
        ss </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> name </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">": "</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> a </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">" + "</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> b </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">" = "</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">a</span><span class="pun" style="color:#ffffff;">+</span><span class="pln" style="color:#ffffff;">b</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
        </span><span class="kwd" style="color:#e28964;">return</span><span class="pln" style="color:#ffffff;"> ss</span><span class="pun" style="color:#ffffff;">.</span><span class="pln" style="color:#ffffff;">str</span><span class="pun" style="color:#ffffff;">();</span><span class="pln" style="color:#ffffff;">
    </span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="pun" style="color:#ffffff;">~</span><span class="typ" style="color:#89bdff;">Foo</span><span class="pun" style="color:#ffffff;">()</span><span class="pln" style="color:#ffffff;">
    </span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
        std</span><span class="pun" style="color:#ffffff;">::</span><span class="pln" style="color:#ffffff;">cout </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"Foo is gone"</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;"><<</span><span class="pln" style="color:#ffffff;"> std</span><span class="pun" style="color:#ffffff;">::</span><span class="pln" style="color:#ffffff;">endl</span><span class="pun" style="color:#ffffff;">;</span><span class="pln" style="color:#ffffff;">
    </span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">
    
</span><span class="kwd" style="color:#e28964;">private</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;">
    std</span><span class="pun" style="color:#ffffff;">::</span><span class="kwd" style="color:#e28964;">string</span><span class="pln" style="color:#ffffff;"> name</span><span class="pun" style="color:#ffffff;">;</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">};</span>

这个类有三个函数,构造函数、Add函数和析构函数。作用是输出不同字符串,以判断各函数是否被调用。

绑定自定义类到Lua

开始前,先了解下绑定C++类的一些基本原理。

首先创建一个userdata来存放C++类对象指针,然后给userdata添加元表,用index元方法映射C++类中的对象方法。

userdata

Lua中userdata为自定义类型,即用户自定义C++类类型,非Lua基本类型。绑定过程中用来存放C++类对象指针,从而将C++类映射到Lua中。

元表(metatable)

带有索引的集合的表,绑定过程中用来存放和映射C++类中的对象和对象方法。

__index

元表索引,指向用来存放userdata的元表。用来索引已创建的元表栈中的C++类名以及类方法名。

接下来完成实现部分,在 fun.cpp 中添加如下代码:

<span class="com" style="color:#aeaeae;FONT-STYLE: italic;">#include</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"fun.h"</span><span class="pln" style="color:#ffffff;">

</span><span class="kwd" style="color:#e28964;">extern</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"C"</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">#include</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;"><lua.h></span><span class="pln" style="color:#ffffff;">
</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">#include</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;"><lauxlib.h></span><span class="pln" style="color:#ffffff;">
</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">#include</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;"><lualib.h></span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">

</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// 1.</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> l_Foo_constructor</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
    </span><span class="kwd" style="color:#e28964;">const</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">char</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> name </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> luaL_checkstring</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">1</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
 
    </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">**</span><span class="pln" style="color:#ffffff;"> udata </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">(</span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">**)</span><span class="pln" style="color:#ffffff;">lua_newuserdata</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">sizeof</span><span class="pun" style="color:#ffffff;">(</span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">*));</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;">udata </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">new</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">name</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="kwd" style="color:#e28964;">return</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">1</span><span class="pun" style="color:#ffffff;">;</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">

</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// 2.</span><span class="pln" style="color:#ffffff;">
</span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l_CheckFoo</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> n</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
    </span><span class="kwd" style="color:#e28964;">return</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">*(</span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">**)</span><span class="pln" style="color:#ffffff;">luaL_checkudata</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> n</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"luaL_Foo"</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">

</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// 3.</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> l_Foo_add</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
    </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> foo </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> l_CheckFoo</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">1</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> a </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> luaL_checknumber</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">2</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    </span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> b </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> luaL_checknumber</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">3</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    
    std</span><span class="pun" style="color:#ffffff;">::</span><span class="kwd" style="color:#e28964;">string</span><span class="pln" style="color:#ffffff;"> s </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> foo</span><span class="pun" style="color:#ffffff;">-></span><span class="typ" style="color:#89bdff;">Add</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">a</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> b</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    lua_pushstring</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> s</span><span class="pun" style="color:#ffffff;">.</span><span class="pln" style="color:#ffffff;">c_str</span><span class="pun" style="color:#ffffff;">());</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="kwd" style="color:#e28964;">return</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">1</span><span class="pun" style="color:#ffffff;">;</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">

</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// 4.</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> l_Foo_destructor</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
    </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> foo </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> l_CheckFoo</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">1</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="kwd" style="color:#e28964;">delete</span><span class="pln" style="color:#ffffff;"> foo</span><span class="pun" style="color:#ffffff;">;</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="kwd" style="color:#e28964;">return</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">0</span><span class="pun" style="color:#ffffff;">;</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">

</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// 5.</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">void</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">RegisterFoo</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
    luaL_Reg sFooRegs</span><span class="pun" style="color:#ffffff;">[]</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;">
    </span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;">
        </span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"new"</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> l_Foo_constructor </span><span class="pun" style="color:#ffffff;">},</span><span class="pln" style="color:#ffffff;">
        </span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"add"</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> l_Foo_add </span><span class="pun" style="color:#ffffff;">},</span><span class="pln" style="color:#ffffff;">
        </span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"__gc"</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> l_Foo_destructor </span><span class="pun" style="color:#ffffff;">},</span><span class="pln" style="color:#ffffff;">
        </span><span class="pun" style="color:#ffffff;">{</span><span class="pln" style="color:#ffffff;"> NULL</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> NULL </span><span class="pun" style="color:#ffffff;">}</span><span class="pln" style="color:#ffffff;">
    </span><span class="pun" style="color:#ffffff;">};</span><span class="pln" style="color:#ffffff;">
    
    luaL_newmetatable</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"luaL_Foo"</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    
    luaL_register</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> NULL</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> sFooRegs</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
   
    lua_setfield</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">-</span><span class="lit" style="color:#3387cc;">1</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"__index"</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    
    lua_setglobal</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"Foo"</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
</span><span class="pun" style="color:#ffffff;">}</span>

代码详解:

1. C++绑定到Lua的构造函数,luaL_checkstring用来检查构造函数的形参是否为string类型并返回这个string。利用lua_newuserdata创建一个userdata来存放Foo类对象指针。luaL_getmetatable将与名为luaL_Foo相关联的元表推入栈中。此时,Lua栈中的内容如下:

<span class="lit" style="color:#3387cc;">3</span><span class="pun" style="color:#ffffff;">|</span><span class="pln" style="color:#ffffff;"> metatable </span><span class="str" style="color:#65b042;">"luaL_foo"</span><span class="pln" style="color:#ffffff;">   </span><span class="pun" style="color:#ffffff;">|-</span><span class="lit" style="color:#3387cc;">1</span><span class="pln" style="color:#ffffff;">
</span><span class="lit" style="color:#3387cc;">2</span><span class="pun" style="color:#ffffff;">|</span><span class="pln" style="color:#ffffff;"> userdata               </span><span class="pun" style="color:#ffffff;">|-</span><span class="lit" style="color:#3387cc;">2</span><span class="pln" style="color:#ffffff;">
</span><span class="lit" style="color:#3387cc;">1</span><span class="pun" style="color:#ffffff;">|</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">string</span><span class="pln" style="color:#ffffff;"> parameter       </span><span class="pun" style="color:#ffffff;">|-</span><span class="lit" style="color:#3387cc;">3</span>

lua_setmetatable 将位于Lua栈中-2位置的 userdata 添加到元表 luaL_foo 中。最后,返回值1使得Lua可以得到userdata,之后栈将会被清空。

2. luaL_checkudata 用来检测形参是否为 luaL_Foo 元表中的userdata,并返回这个userdata。

3. 此函数是将C++类中的Add()函数映射到Lua中, lua_pushstring 将字符串压入栈中,返回值1使得字符串返回给Lua调用函数。

4. 此函数是将C++类中的析构函数映射到Lua中。

5. 此函数是注册C++类到Lua和注册所有已绑定的C++函数到Lua。 sFooRegs 给每个已绑定的C++函数一个能被Lua访问的名字。 luaL_newmetatable 创建一个名为luaL_Foo的元表并压入栈定, luaL_register 将 sFooRegs 添加到luaL_Foo中。 lua_pushvalue 将luaL_Foo元表中元素的拷贝压入栈中。 lua_setfield 将luaL_Foo元表的index域设为 __index 。 lua_setglobal 将元表luaL_Foo重命名为Foo并将它设为Lua的全局变量,这样Lua可以通过识别Foo来访问元表luaL_Foo,并使Lua脚本能够覆盖元表Foo,即覆盖C++函数。如此一来,用户可以用Lua代码自定功能,覆盖掉C++类中函数的功能,极大地提高了代码灵活性。

现在添加绑定函数的函数声明至 fun.h 中:

<span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> l_Foo_constructor</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">

</span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l_CheckFoo</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> n</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">

</span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> l_Foo_add</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">

</span><span class="kwd" style="color:#e28964;">int</span><span class="pln" style="color:#ffffff;"> l_Foo_destructor</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">

</span><span class="kwd" style="color:#e28964;">void</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">RegisterFoo</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">lua_State </span><span class="pun" style="color:#ffffff;">*</span><span class="pln" style="color:#ffffff;"> l</span><span class="pun" style="color:#ffffff;">);</span>

Lua测试代码

添加如下代码到 fun.lua :

<span class="kwd" style="color:#e28964;">function</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;">speak</span><span class="pun" style="color:#ffffff;">()</span><span class="pln" style="color:#ffffff;">
    </span><span class="kwd" style="color:#e28964;">print</span><span class="pun" style="color:#ffffff;">(</span><span class="str" style="color:#65b042;">"Hello, I am a Foo"</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">end</span><span class="pln" style="color:#ffffff;">
 
</span><span class="kwd" style="color:#e28964;">local</span><span class="pln" style="color:#ffffff;"> foo </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pun" style="color:#ffffff;">.</span><span class="kwd" style="color:#e28964;">new</span><span class="pun" style="color:#ffffff;">(</span><span class="str" style="color:#65b042;">"fred"</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">local</span><span class="pln" style="color:#ffffff;"> m </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> foo</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;">add</span><span class="pun" style="color:#ffffff;">(</span><span class="lit" style="color:#3387cc;">3</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">4</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
 
</span><span class="kwd" style="color:#e28964;">print</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">m</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
 
foo</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;">speak</span><span class="pun" style="color:#ffffff;">()</span><span class="pln" style="color:#ffffff;">
 
</span><span class="typ" style="color:#89bdff;">Foo</span><span class="pun" style="color:#ffffff;">.</span><span class="pln" style="color:#ffffff;">add_ </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pun" style="color:#ffffff;">.</span><span class="pln" style="color:#ffffff;">add
</span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// 1.</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">function</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;">add</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">a</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> b</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
    </span><span class="kwd" style="color:#e28964;">return</span><span class="pln" style="color:#ffffff;"> </span><span class="str" style="color:#65b042;">"here comes the magic: "</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">..</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">self</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;">add_</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">a</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> b</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
</span><span class="kwd" style="color:#e28964;">end</span><span class="pln" style="color:#ffffff;">
 
m </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> foo</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;">add</span><span class="pun" style="color:#ffffff;">(</span><span class="lit" style="color:#3387cc;">9</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">8</span><span class="pun" style="color:#ffffff;">)</span><span class="pln" style="color:#ffffff;">
 
</span><span class="kwd" style="color:#e28964;">print</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">m</span><span class="pun" style="color:#ffffff;">)</span>

1. 同名函数覆盖绑定的C++函数,提高扩展性。

绑定检测

将 #include “fun.h” 添加至 AppDelegate.cpp 中,并在 AppDelegate.cpp 中的 applicationDidFinishLaunching 函数中添加如下代码:

<span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// register lua engine</span><span class="pln" style="color:#ffffff;">
    </span><span class="kwd" style="color:#e28964;">auto</span><span class="pln" style="color:#ffffff;"> engine </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">LuaEngine</span><span class="pun" style="color:#ffffff;">::</span><span class="pln" style="color:#ffffff;">getInstance</span><span class="pun" style="color:#ffffff;">();</span><span class="pln" style="color:#ffffff;">
    </span><span class="typ" style="color:#89bdff;">ScriptEngineManager</span><span class="pun" style="color:#ffffff;">::</span><span class="pln" style="color:#ffffff;">getInstance</span><span class="pun" style="color:#ffffff;">()-></span><span class="pln" style="color:#ffffff;">setScriptEngine</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">engine</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// Adding code here...</span><span class="pln" style="color:#ffffff;">
    </span><span class="com" style="color:#aeaeae;FONT-STYLE: italic;">// register lua binding</span><span class="pln" style="color:#ffffff;">
    
    </span><span class="typ" style="color:#89bdff;">RegisterFoo</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">engine</span><span class="pun" style="color:#ffffff;">-></span><span class="pln" style="color:#ffffff;">getLuaStack</span><span class="pun" style="color:#ffffff;">()-></span><span class="pln" style="color:#ffffff;">getLuaState</span><span class="pun" style="color:#ffffff;">());</span><span class="pln" style="color:#ffffff;">
    
    std</span><span class="pun" style="color:#ffffff;">::</span><span class="kwd" style="color:#e28964;">string</span><span class="pln" style="color:#ffffff;"> path </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">FileUtils</span><span class="pun" style="color:#ffffff;">::</span><span class="pln" style="color:#ffffff;">getInstance</span><span class="pun" style="color:#ffffff;">()-></span><span class="pln" style="color:#ffffff;">fullPathForFilename</span><span class="pun" style="color:#ffffff;">(</span><span class="str" style="color:#65b042;">"fun.lua"</span><span class="pun" style="color:#ffffff;">);</span><span class="pln" style="color:#ffffff;">
    engine</span><span class="pun" style="color:#ffffff;">-></span><span class="pln" style="color:#ffffff;">executeScriptFile</span><span class="pun" style="color:#ffffff;">(</span><span class="pln" style="color:#ffffff;">path</span><span class="pun" style="color:#ffffff;">.</span><span class="pln" style="color:#ffffff;">c_str</span><span class="pun" style="color:#ffffff;">());</span>

注意: 因为Cocos2d-x Lua Binding目前不支持多个状态,所以在注册已绑定的C++类时,只能使用当前运行的状态。

运行程序,如果得到下面的输出结果证明已经绑定成功:

<span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;"> </span><span class="kwd" style="color:#e28964;">is</span><span class="pln" style="color:#ffffff;"> born
cocos2d</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">[</span><span class="pln" style="color:#ffffff;">LUA</span><span class="pun" style="color:#ffffff;">-</span><span class="kwd" style="color:#e28964;">print</span><span class="pun" style="color:#ffffff;">]</span><span class="pln" style="color:#ffffff;"> fred</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">3</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">+</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">4</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">7</span><span class="pln" style="color:#ffffff;">
cocos2d</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">[</span><span class="pln" style="color:#ffffff;">LUA</span><span class="pun" style="color:#ffffff;">-</span><span class="kwd" style="color:#e28964;">print</span><span class="pun" style="color:#ffffff;">]</span><span class="pln" style="color:#ffffff;"> </span><span class="typ" style="color:#89bdff;">Hello</span><span class="pun" style="color:#ffffff;">,</span><span class="pln" style="color:#ffffff;"> I am a </span><span class="typ" style="color:#89bdff;">Foo</span><span class="pln" style="color:#ffffff;">
cocos2d</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">[</span><span class="pln" style="color:#ffffff;">LUA</span><span class="pun" style="color:#ffffff;">-</span><span class="kwd" style="color:#e28964;">print</span><span class="pun" style="color:#ffffff;">]</span><span class="pln" style="color:#ffffff;"> here comes the magic</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;"> fred</span><span class="pun" style="color:#ffffff;">:</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">9</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">+</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">8</span><span class="pln" style="color:#ffffff;"> </span><span class="pun" style="color:#ffffff;">=</span><span class="pln" style="color:#ffffff;"> </span><span class="lit" style="color:#3387cc;">17</span>

Android环境测试:

如果希望在Android环境下调试,在执行 proj.android/build_native 脚本前,需要在 proj.android/jni/Android.mk 文件中添加 fun.cpp 文件包含:

<span class="pln" style="color:#ffffff;">LOCAL_SRC_FILES </span><span class="pun" style="color:#ffffff;">:=</span><span class="pln" style="color:#ffffff;"> hellolua</span><span class="pun" style="color:#ffffff;">/</span><span class="pln" style="color:#ffffff;">main</span><span class="pun" style="color:#ffffff;">.</span><span class="pln" style="color:#ffffff;">cpp \
                   </span><span class="pun" style="color:#ffffff;">../../</span><span class="typ" style="color:#89bdff;">Classes</span><span class="pun" style="color:#ffffff;">/</span><span class="typ" style="color:#89bdff;">AppDelegate</span><span class="pun" style="color:#ffffff;">.</span><span class="pln" style="color:#ffffff;">cpp \
                   </span><span class="pun" style="color:#ffffff;">../../</span><span class="typ" style="color:#89bdff;">Classes</span><span class="pun" style="color:#ffffff;">/</span><span class="pln" style="color:#ffffff;">fun</span><span class="pun" style="color:#ffffff;">.</span><span class="pln" style="color:#ffffff;">cpp</span>

项目文件在此下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值