vs2010中使用luabind

第一部分:在vs2010中生成luabind靜態庫和動態庫linux

1、前期準備 1.安裝boostios

下載boost並解壓到 D:\mylua\boost_1_56_0,進入 D:\mylua\boost_1_56_0\tools\build 運行 bootstrap.bat文件,先編譯 bjam.exe,再使用 bjam.exe編譯boost庫。(運行bjam.exe編譯boost庫比較耗時,請耐心等待。)

2.下載並生成lua靜態庫bootstrap

請參考個人文章《lua如何在VS2010中配置靜態庫》,網址爲: 點擊打開連接
這裏有一個注意事項,那就是luabind咱們若是是下載的是luabind-0.9.1,那麼lua要下載5.1版本,貌似5.20也能夠,可是我沒有去嘗試。
解壓縮包,例如我解壓縮到E:\lua\lua-5.1 (本人爲:D:\mylua\lua-5.1.4\src)
(本人使用D:\mylua\lua-5.1.4版本的源代碼, 由於本人安裝的lua版本爲lua-5.1.4)
注:本人因引用的lua版本源代碼和安裝的lua版本不匹配,致使一直出現 「找不到標識符」的錯誤。引覺得注。
(lua配置環境變量網上查找相關資料,有不少,也簡單。)

3.下載luabind源代碼安全

下載網址: 點擊打開連接,解壓縮包,例如我解壓縮到E:\lua\luabind-0.9.1(本人爲:D:\mylua\luabind-0.9.1)

2、生成靜態庫 框架

1.使用嚮導生成項目/解決方案編輯器

使用vs2010的嚮導生成靜態庫項目,去掉「使用預編譯頭」複選框,取名叫作luabind_lib,文件夾爲E:\lua\luabind_lib

2.添加luabind源代碼文件svn

(1)右擊工程項目"luabind_lib"的「頭文件「文件夾  ->添加->新建篩選器,重命名爲detail(其實就是添加一個新的虛擬的分類文件夾);
(2)右擊「detail「文件夾->添加->現有項->選擇E:\lua\luabind-0.9.1\luabind-0.9.1\luabind\detail目錄下的文件添加;(本人爲:D:\mylua\luabind-0.9.1\luabind\detail)
(3)右擊」頭文件「->添加->現有項->選擇E:\lua\luabind-0.9.1\luabind-0.9.1\luabind目錄中除detail文件夾以外的文件。(本人爲:D:\mylua\luabind-0.9.1\luabind)
(4)右擊」源文件「文件夾 ->添加->現有項->選擇E:\lua\luabind-0.9.1\luabind-0.9.1\src目錄下的全部文件(本人爲:D:\mylua\lua-5.1.4\src)

3.添加包含目錄函數

由於luabind用的是boost中的模板元編寫 寫的,因此須要包含boost目錄,他是鏈接C++和lua的橋樑,因此須要包含lua,最後還要包含他本身添加luabind源代碼文件的目錄。
右擊luabind_lib項目->屬性->配置屬性->C/C++->常規->附加包含目錄 添加:
  a. luabind 源文件目錄:E:\lua\luabind-0.9.1\luabind-0.9.1(注意是外層目錄)(本人爲:D:\mylua\luabind-0.9.1)
  b. lua源文件目錄:E:\lua\lua-5.1\lua-5.1\src (本人爲:D:\mylua\lua-5.1.4\src)
  c. boost源文件目錄:D:\Program Files %28x86%29\bost\boost_1_54_0(這個以前就安裝好了)(本人爲:D:\mylua\boost_1_56_0)

4.生成靜態庫工具

右擊生成解決方案/項目,生成靜態庫(C:\Users\Administrator\Documents\Visual Studio 2010\Projects\luabind_lib\Debug目錄多了一個靜態庫:luabind_lib.lib)
 
3、使用靜態庫
1.新建一個控制檯項目取名luabind_test2 。
2.添加代碼:
#include "stdafx.h"

#include <iostream>



extern "C" 
{     
#include "lua.h"     
#include "lualib.h"     
#include "lauxlib.h" 
} 
#include <iostream> 
#include <luabind/luabind.hpp>

using namespace std;



int _tmain(int argc, _TCHAR* argv[])
{
    lua_State *L = ::luaL_newstate();  /* opens Lua */
    luabind::open(L);

    luaL_dostring(L,"function add(first,second)\n return first + second\n end\n");

    try{
        std::cout<<"Result:"
            <<luabind::call_function<int>(L,"add",2,3)<<std::endl;
    }
    catch(luabind::error& e){
        std::cout<<"catch exception:"<<e.what()<<std::endl;
    }
    ::lua_close(L);

}

3.添加包含目錄性能

右擊luabind_test項目->屬性->配置屬性->C/C++->常規->附加包含目錄 添加:
  a.luabind 源文件目錄:E:\lua\luabind-0.9.1\luabind-0.9.1(注意是外層目錄)
  b.lua源文件目錄:E:\lua\lua-5.1\lua-5.1\src
  c.boost源文件目錄:D:\Program Files %28x86%29\bost\boost_1_54_0(這個以前就安裝好了)
4.添加上面作好的luabind靜態庫,這裏使用直接添加依賴項目:
  右擊解決方案->添加->現有項目->E:\lua\luabind_lib\luabind_lib\luabind_lib\ luabind_lib.vcxproj(本人爲:C:\Users\Administrator\Documents\Visual Studio 2010\Projects\luabind_lib\luabind_lib\luabind_lib.vcxproj)
  設置好依賴關係:在項目luabind_test2上右鍵 ->項目依賴項->勾選luabind_lib。
  配置依賴關係: 右擊luabind-test項目->屬性->通用屬性->框架和引用->添加新引用->添加的兩個靜態庫
5. 添加lua 靜態庫(連接器->輸入->附加依賴項->添加 lua5.1.lib),VC++目錄(lua 包含目錄和庫目錄(在lua安裝路徑下))
注:生成成功,會在C:\Users\Administrator\Documents\Visual Studio 2010\Projects\luabind_test2\Debug目錄下生成luabind_lib.lib靜態庫和luabind_test2.exe可執行文件。
編譯運行,運行結果」Result:5「(一閃而過)
 
添加框架引用:
 
4、生成動態庫dll
1. 在VS中新建一個控制檯項目,類型爲DLL,命名項目爲hello_dll_luabind,而後輸入一下代碼:
#include "stdafx.h"
#include <iostream>
#include <luabind/luabind.hpp>
void greet()
{
    std::cout << "hello world!\n";
}

extern "C" int __declspec(dllexport) init(lua_State* L)
{
    using namespace luabind;

    open(L);

    module(L)
    [
        def("greet", &greet)
    ];

    return 0;
}

 注意,在Windows環境下init函數以前是要加__declspec(dllexport)才能將函數導出的,而luabind的文檔中的環境是linux,默認不用加__declspec(dllexport)也能夠導出(就由於這個折騰了我半天才把hello word成功運行)。

2. 添加靜態庫文件:將luabind.lib和lua51.lib添加到連接選項中:項目屬性->鏈接器->輸入->附加依賴文件,加入luabind.lib和lua51.lib(這裏我把luabind.lib拷貝到我工程項目根目錄下:C:\Users\Administrator\Documents\Visual Studio 2010\Projects\hello_dll_luabind\luabind_lib.lib)。

接着:在項目->屬性->VC++目錄->包含目錄和庫目錄中分別添加luabind.lib和lua51.lib所在目錄,以及代碼中包含文件的目錄。同時須要把D:\mylua\boost_1_56_0目錄引入(luabind須要用到boost庫相關頭文件)。以下圖:

3.編譯運行將在工程項目文件目錄 C:\Users\Administrator\Documents\Visual Studio 2010\Projects\hello_dll_luabind\Debug 下獲得hello_dll_luabind.dll文件。

4. 把hello_dll_luabind.dll放到lua51.dll和lua.exe所在的目錄下。打開lua命令行,鍵入:

測試成功。cheer!

 後補:
1、當我把代碼中的init函數名改成luaopen_hello_dll_luabind時(注意和項目工程名同樣),從新生成動態庫,拷貝到lua51.dll和lua.exe所在目錄,能夠以下運行:
 bingo!
2、使用Sublime工具來編寫lua(本人使用感受挺不錯的一款文本編輯器,提供了各類插件對lua的支持,具體網上有不少資料可供參考。)
配置好Sublime以後(使用lua編譯系統,svn插件等),鍵入以下程序,ctrl+B 運行,結果截圖以下:
這裏涉及到require在加載模塊時的一些規則,詳見《lua程序設計(第二版)》
 【參考】http://www.aichengxu.com/view/13671
 
第二部分:luabind使用語法(詳細內容可參見《luabind使用手冊》)
  6 做用域
註冊到Lua裏面的全部東西要不註冊於一個名空間下(Lua table)要不註冊於全局做用域(lua module).
全部註冊的東西必須放在一個做用域裏面.爲了定義一個模塊, luabind::module 類必須被使用.
使用方式以下:
module(L)
[
// declarations
];

這將會註冊全部的函數或者類到 Lua 全局做用域. 若是你想要爲你的模塊設定一個名空間(相似標準模塊),

你能夠給構造函數設定一個名字,例如:
module(L, "my_library")
[
// declarations
];

這裏全部的申明都將被放置在 my_libary 表.


若是你想要嵌套名空間,你能夠用 luabind::namespace_ 類. 它和 luabind::module 相似,除了構造器
沒有lua_State* 輸入參數.用例以下:
module(L, "my_library")
[
// declarations

namespace_("detail")
[
// library-private declarations
]
];

你可能會想到,下面兩個聲明是等價的:

module(L)
[
namespace_("my_library")
[
// declarations
]

];
module(L, "my_library")
[
// declarations
];

每個聲明必須用逗號分隔,例如:

module(L)
[
def("f", &f),
def("g", &g),
class_<A>("A")
.def(constructor<int, int>),
def("h", &h)
];

 

更多實際的例子請參閱  綁定函數到Lua 和 綁定類到Lua 章節.

請注意, (若是你對性能有很高的需求)把你的函數放到表裏面將增長查找函數的時間.

7 綁定函數到Lua

爲了綁定函數到Lua,你可使用函數 luabind::def(). 它的聲明以下:
template<class F, class policies>
void def(const char* name, F f, const Policies&);

* name 是該函數在Lua裏面的名字

* F 是該函數的指針
* 策略參數是用來描述怎樣處理該函數參數和返回值的.這是一個可選參數,參見 策略 章節.

下面的例子演示註冊函數 float std::sin(float):
module(L)
[
def("sin", &std::sin)
];

7.1 重載函數


若是你有同名函數須要註冊到Lua, 你必須顯示的給定函數的簽名.
這可讓C++知道你指定的是哪個函數. 例如, 若是你有兩個函數,
int f(const char*) 和 void f(int).
module(L)
[
def("f", (int(*)(const char*)) &f),
def("f", (void(*)(int)) &f)
];

7.2 簽名匹配


LuaBind 將會生成代碼來檢查Lua棧的內容是否匹配你的函數的簽名. 它會隱式的在
派生類之間進行類型轉換,而且它會按照儘可能少進行隱式類型轉換的原則經行匹配.在
一個函數調用中,若是函數是重載過的,而且重載函數的參數匹配分不出好壞的話
(都經行一樣次數的隱式類型轉換),那麼將產生一個二義性錯誤.這將生成一個運行時
錯誤,程序掛起在產生二義性調用的地方.一個簡單的例子是,註冊兩個函數,一個函數
接受一個int參數,另一個函數接受一個float參數. 由於Lua將不區別浮點數和整形數,
因此他們都是匹配的.

由於全部的重載是被測試過的,這將老是找到最好的匹配(不是第一個匹配).這樣意味着,
LuaBind能夠處理簽名的區別只是const和非const的重載函數.

例如,若是以下的函數和類被註冊:
struct A
{
void f();
void f() const;
};

const A* create_a();全部權轉移

爲了正確處理全部權轉移問題,create_a()將用來適配返回值策略.
參見 策略 章節.                               
-Linker Lin 4/5/08 6:32 PM

struct B: A {};
struct C: B {};

void g(A*);
void g(B*);

執行如下 Lua 代碼即結果:

a1 = create_a()
a1:f() -- 常量版本被調用

a2 = A()
a2:f() -- 很是量版本被調用

a = A()
b = B()
c = C()

g(a) -- calls g(A*)
g(b) -- calls g(B*)
g(c) -- calls g(B*)

7.3 調用Lua函數


爲了調用一個Lua函數, 你能夠或者用 call_function() 或者用 一個對象(object).
template<class Ret>
Ret call_function(lua_State* L, const char* name, ...)
template<class Ret>
Ret call_function(object const& obj, ...)

call_function()函數有兩個重載版本.一個是根據函數的名字來調用函數,

另外一個是調用一個能夠做爲函數調用的Lua值.

使用函數名來調用的版本只能調用Lua全局函數.
"..."表明傳遞給Lua函數的可變個數的參數. 這使得你能夠指定調用的策略.你能夠經過 operator[] 來實現
這個功能.你能夠同過方括號來指定策略,例如:
int ret = call_function<int>(
L
, "a_lua_function"
, new complex_class()
)[ adopt(_1) ];

若是你想經過引用方式傳遞參數,你必須用Boost.Ref來包裝一下.

例如:
int ret = call_function(L, "fun", boost::ref(val));

若是你想給一個函數調用指定本身的錯誤捕獲處理函數(error handler),能夠參閱

pcall errorfunc 章節的 set_pcall_callback .

7.4 使用Lua協程

爲了使用Lua協程,你必須調用 lua_resume(),這就意味着你不能用先前介紹的函數
call_function()來開始一個協程.你必須用這個:
template<class Ret>
Ret resume_function(lua_State* L, const char* name, ...)
template<class Ret>
Ret resume_function(object const& obj, ...)

和:

template<class Ret>
Ret resume(lua_State* L, ...)

第一次開始一個協程的時候,你必須給它一個入口函數. 當一個協程返回(yield)的時候,

resume_fucntion()調用的返回值是 lua_yield()的第一個傳入參數.當你想要繼續一個
協程的時候,你只須要調用 resume() 在你的 lua_State() 上,由於它已經在執行一個函數
(即先前出入的入口函數),因此你不須要再次傳入函數.resume()的傳入參數將做爲Lua側的
yield()調用的返回值.

爲了暫停(yielding)C++函數,(不支持在C++側和Lua側傳送數據塊),你可使用 yield 策略.

接受 object 參數的resume_function()的重載版本要求對象必須是一個協程對象.(thread)

lua_State* thread = lua_newthread(L);
object fun = get_global(thread)["my_thread_fun"];
resume_function(fun);

8 綁定類到Lua


爲了註冊一個類,你能夠用 class_ 類. 它的名字和C++關鍵字相似是爲了比較直觀.它有一個重載
過的成員函數 def() .這個函數被用來註冊類的成員函數,操做符,構造器,枚舉和屬性.它將返回 this
指針,從而方便你直接註冊更多的成員.

讓咱們開始一個簡單的例子.考慮下面的C++類:
class testclass
{
public:
testclass(const std::string& s): m_string(s) {}
void print_string() { std::cout << m_string << "\n"; }

private:
std::string m_string;
};

爲了註冊這個類到Lua環境,能夠像下面這樣寫(假設你使用了名空間):

module(L)
[
class_<testclass>("testclass")
.def(constructor<const std::string&>())
.def("print_string", &testclass::print_string)
];

這將註冊 testclass 類以及接受一個string參數的構造器以及一個成員叫print_string()的函數.

Lua 5.0  Copyright (C) 1994-2003 Tecgraf, PUC-Rio
> a = testclass('a string')
> a:print_string()
a string

還能夠註冊自由函數做爲成員函數.對這個自由函數的要求是,它必須接受該類的一個指針或常量指針或
引用或常量引用做爲函數的第一個參數.該函數的剩下的參數將在Lua側可見,而對象指針將被賦值給第一個
參數.若是咱們有以下的C++代碼:
struct A
{
int a;
};

int plus(A* o, int v) { return o->a + v; }

你能夠註冊 plus() 做爲A的一個成員函數,以下:

class_<A>("A")
.def("plus", &plus)

plus() 如今可以被做爲A的一個接受一個int參數的成員函數來調用.若是對象指針(this指針)是const,

這個函數也將表現的像一個常量成員函數那樣(它能夠經過常量對象來調用).

8.1 重載成員函數

當綁定超過一個以上的重載過的成員函數的時候,或只是綁定其中的一個的時候,你必須消除你傳遞給 def() 的
成員函數指針的歧義.爲此,你能夠用普通C風格的類型轉換來轉型匹配正確的重載函數. 爲此,你必須知道怎麼去
描述C++成員函數的類型.這裏有一個簡短的教程(更多信息請查閱你的C++參考書):
成員函數指針的語法以下:
return-value (class-name::*)(arg1-type, arg2-type, ...)

例如:

struct A
{
void f(int);
void f(int, int);
};
class_<A>()
.def("f", (void(A::*)(int))&A::f)

A的第一個成員函數f(int)被綁定了,而第二個沒喲被綁定.


8.2 屬性

很容易註冊類的全局數據成員.考慮以下的類:
struct A
{
int a;
};

這個類能夠這樣註冊:

module(L)
[
class_<A>("A")
.def_readwrite("a", &A::a)
];

這使得成員變量 A::a 得到了讀寫訪問權. 還能夠註冊一個只讀的屬性:

module(L)
[
class_<A>("A")
.def_readonly("a", &A::a)
];

當綁定成員是一個非原始數據類型的時候,自動生成的 getter 函數將會返回一個它引用.

這就容許你能夠鏈式使用 . 操做符.例如,當有一個結構體包含另一個結構體的時候.以下:
struct A { int m; };
struct B { A a; };

當綁定B到Lua的時候,下面的表達式應該能夠工做:

b = B()
b.a.m = 1
assert(b.a.m == 1)

這要求 a 屬性必須返回一個A的引用, 而不是一個拷貝. 這樣,LuaBind將會自動使用依賴策略來

確保返回值依賴於它所在的對象.因此,若是返回的引用的生命長於該對象的全部的引用(這裏是b).
它將保持對象是激活的,從而避免出現懸掛指針.

你還能夠註冊 getter 或者 setter 函數來使得它們看上去像一個 public 的成員.考慮下面的類:
class A
{
public:
void set_a(int x) { a = x; }
int get_a() const { return a; }

private:
int a;
};

能夠這樣註冊成一個公共數據成員:

class_<A>("A")
.property("a", &A::get_a, &A::set_a)

這樣 set_a() 和 get_a() 將取代簡單的數據成員操做.若是你想使之只讀,你只須要省略最後一個參數.

請注意, get 函數必須是 const 的,不然不能經過編譯.

8.3 枚舉

若是你的類包含枚舉,你能夠註冊它們到Lua. 注意,它們不是類型安全的,全部的枚舉在Lua側都是整型的,
而且全部接受枚舉參數的函數都將接受任何整型.你能夠像這樣註冊它們:

module(L)
[
class_<A>("A")
.enum_("constants")
[
value("my_enum", 4),
value("my_2nd_enum", 7),
value("another_enum", 6)
]
];

在Lua側,他們能夠像數據成員那樣被操做,除了它們是隻讀的並且屬於類自己而不是類的實例.

Lua 5.0  Copyright (C) 1994-2003 Tecgraf, PUC-Rio
> print(A.my_enum)
4
> print(A.another_enum)
6

8.4 操做符

爲了綁定操做符,你須要包含頭文件 <luabind/operator.hpp>.
註冊你的類的操做符的機制很是的簡單.你經過一個全局名字 luabind::self 來引用類本身,而後你就
能夠在def()調用裏面直接用操做符表達式. 類以下:
struct vec
{
vec operator+(int s);
};

能夠這樣註冊:

module(L)
[
class_<vec>("vec")
.def(self + int())
];

無論你的 + 操做符是定義在類裏面仍是自由函數均可以工做.

若是你的操做符是常量的(const)(或者,是一個自由函數, 接受一個類的常量的引用)你必須用
const_self 替代 self. 以下:
module(L)
[
class_<vec>("vec")
.def(const_self + int())
];

支持以下操做符:

+    -    *    /    ==    <    <=

這意味着,沒有"就地操做符"(in-place)(++ --). 相等操做符(==)有些敏銳;若是引用是相等的就不會
被調用. 這意味着, 相等操做符的效率很是好.

Lua不支持操做符包括: !=,>和<=.這是爲何你只能註冊上面那些操做符. 當你調用這些操做符的時候,
Lua會把調用轉換到支持的操做符上.(譯註:例如:==和!=有 邏輯非 的關係) -Linker Lin 4/6/08 11:09 PM

在上面的示例中,操做數的類型是 int().若是操做數的類型是複雜類型,就不是那麼簡單了,你須要用 other<>
來包裝下.例如:
爲了註冊以下的類,咱們不想用一個string的實例來註冊這個操做符.
struct vec
{
vec operator+(std::string);
};

取而代之的是,咱們用 other<> 包裝下,以下:

module(L)
[
class_<vec>("vec")
.def(self + other<std::string>())
];

註冊一個應用程序操做符(函數調用):

module(L)
[
class_<vec>("vec")
.def( self(int()) )
];

這裏有個特殊的操做符.在Lua裏,它叫作 __tostring,它不是一個真正的操做符.它是被用來轉換一個對象到

string的標準Lua方法.若是你註冊之,能夠經過Lua的標準函數 tostring() 來轉換你的對象到一個string.

爲了在C++裏實現這個操做符,你須要爲 std::ostream 提供 operator<< .像這樣:
class number {};
std::ostream& operator<<(std::ostream&, number&);

...

module(L)
[
class_<number>("number")
.def(tostring(self))
];

 

8.5 嵌套做用域和靜態函數

能夠添加嵌套的做用域到一個類.當你須要包裝一個嵌套類或者一個靜態函數的時候就會頗有用.
class_<foo>("foo")
.def(constructor<>()
.scope
[
class_<inner>("nested"),
def("f", &f)
];

在上面的例子裏, f 將表現的像一個類 foo 的靜態函數,而 類 nested 將表現的像類 foo 的嵌套類.


還能夠用一樣的語法添加名空間到類裏面.


8.6 繼承類

若是你想要註冊一個繼承自其它類的類到Lua, 你能夠指定一個模板參數 bases<> 給 class_ 的構造器.
以下的繼承關係:
struct A {};
struct B : A {};

能夠這樣註冊:

module(L)
[
class_<A>("A"),
class_<B, A>("B")
];

若是你使用了多繼承,你能夠指定多於一個的基類.若是 B 還繼承了類 C , 它能夠這樣註冊:

module(L)
[
class_<B, bases<A, C> >("B")
];

注意,你能夠省去 bases<> 當你用的是單繼承的時候.


注意
若是你不指定類的繼承關係, LuaBind 將不能在相關的繼承類型間進行隱式類型轉換.


8.7 智能指針

當你註冊一個類的時候,你能夠告訴 LuaBind 全部的該類的實例應該被某種智能指針持有.(例如: boost::shared_ptr)
你可經過把一個 持有器類型模板參數 給 class_ 類的構造器來實現該功能.例如:
module(L)
[
class_<A, boost::shared_ptr<A> >("A")
];

你還必須爲你的智能指針提供兩個函數.一個返回常量版本的智能指針類型(這裏是: boost:shared_ptr< const A >).

另外一個函數要能夠從智能指針萃取流指針(raw pointer). 之因此須要第一個函數是由於,LuaBind 容許
很是量 -> 轉換在傳遞Lua值到C++的時候.之因此須要第二個函數是由於,當Lua調用一個被智能指針持有
的類的成員函數的時候,this 指針必須是一個流指針.還有一個緣由是,從Lua轉換到C++的時候,須要實現
智能指針到普通指針的轉換.看上去像這樣:
namespace luabind {

template<class T>
T* get_pointer(boost::shared_ptr<T>& p)
{
return p.get();
}

template<class A>
boost::shared_ptr<const A>*
get_const_holder(boost::shared_ptr<A>*)
{
return 0;
}
}

第二個函數只在編譯時用於映射 boost::shared_ptr<A>到其常量版本 boost::shared_ptr<const A>.

它歷來不會被調用,因此返回值是無所謂的(返回值的類型纔是關鍵).

這個轉換將這樣工做(假定 B 是A的基類):
從Lua到C++
Source     Target
holder_type<A>     A*
holder_type<A>     B*
holder_type<A>     A const*
holder_type<A>     B const*
holder_type<A>     holder_type<A>
holder_type<A>     holder_type<A const>
holder_type<A const>     A const*
holder_type<A const>     B const*
holder_type<A const>     holder_type<A const

從C++到Lua

Source     Target
holder_type<A>     holder_type<A>
holder_type<A const>     holder_type<A const>
holder_type<A> const&     holder_type<A>
holder_type<A const> const&     holder_type<A const>

當使用持有器類型的時候,知道指針是否是合法(例如:非空)是頗有用的.例如,當使用 std::auto_ptr 的時候,

持有器經過一個參數傳遞給函數的時候將會變得無效. 爲了這個目的,全部的對象實例都有一個成員叫: __ok.

struct X {};
void f(std::auto_ptr<X>);

module(L)
[
class_<X, std::auto_ptr<X> >("X")
.def(constructor<>()),

def("f", &f)
];

Lua 5.0 Copyright (C) 1994-2003 Tecgraf, PUC-Rio

> a = X()
> f(a)
> print a.__ok
false


當註冊一個繼承樹的時候,全部的實例被智能指針持有的地方,全部的類必須包含持有器類型.例如:

module(L)
[
class_<base, boost::shared_ptr<base> >("base")
.def(constructor<>()),
class_<derived, base, boost::shared_ptr<base> >("base")
.def(constructor<>())
];

 

在內部, LuaBind 將會作必要的轉換於萃取自持有器的流指針之上.

8.8 拆分類註冊

在某些狀況下,可能須要分開註冊一個類在不一樣的編譯單元. 部分緣由多是節約重編譯時間,而某些編譯器的
限制可能要求不得不分開註冊一個類.其實很簡單.考慮下面的示例代碼:

void register_part1(class_<X>& x)
{
x.def();
}

void register_part2(class_<X>& x)
{
x.def();
}

void register_(lua_State* L)
{
class_<X> x("x");

register_part1(x);
register_part2(x);

module(L) [ x ];
}

這裏,類X被分兩步註冊.兩個函數 register_part 和 register_part2 可能被放到不一樣的編譯單元裏.

關於分開註冊一個模塊的信息請參閱: 分開註冊 章節.
相關文章
相關標籤/搜索