第一部分:在vs2010中生成luabind静态库和动态库

一、前期准备 1.安装boost

下载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静态库

请参考我的文章《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)

二、生成静态库 

1.使用向导生成项目/解决方案

使用vs2010的向导生成静态库项目,去掉“使用预编译头”复选框,取名叫做luabind_lib,文件夹为E:\lua\luabind_lib

2.添加luabind源代码文件

(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)
 
三、使用静态库
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",,)<<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“(一闪而过)
 
添加框架引用:
 
四、生成动态库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 ;
}

注意,在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!

 后补:
一、当我把代码中的init函数名改为luaopen_hello_dll_luabind时(注意和项目工程名一样),重新生成动态库,拷贝到lua51.dll和lua.exe所在目录,可以如下运行:
 bingo!
二、使用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 =
assert(b.a.m == )

这要求 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", ),
value("my_2nd_enum", ),
value("another_enum", )
]
];

在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 ;
}
}

第二个函数只在编译时用于映射 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 可能被放到不同的编译单元里.

关于分开注册一个模块的信息请参阅: 分开注册 章节.

 
 
 

vs2010中使用luabind的更多相关文章

  1. VS2010中项目发布遇到的应用程序池问题(无法识别的属性“targetFramework”)

    1.错误情况 2.原因:VS2010中你的应用程序的目标框架与IIS中的应用程序池不同.VS2010中的是.Net Framework4.0,而本机IIS是.Net Framework2.0 3.解决 ...

  2. win7中VS2010中安装CSS3.0问题解决方法

    win7中VS2010中安装CSS3.0问题解决方法   在安装Standards Update for VS2010 SP1后,VS2010中没有CSS3.0问题,以下是我的解决方法 1.首先去官网 ...

  3. VS2010中汉字拷贝到Word出现乱码问题解决

    VS2010中的汉字拷贝到Word时出现乱码,有三种解决方法: 一.粘贴时,选择“仅保留文本”.如图: 二.先拷贝粘贴到记事本文件内,此时会自动过滤格式信息,再从记事本拷贝到Word. 三.使用转换软 ...

  4. VS2010中App_Code文件夹的问题

    在VS2010中新建一个Web Application,然后新建一个app_Code文件夹, 在app_code文件夹下建一个ClassHelper类. 然后在index页面中使用ClassHelpe ...

  5. vs2010中的MSBuild输出warning MSB8012问题

    vs2010中,MSBuild与C++编译器无缝整合.无论使用vs2010生成的代码,还是转换vs2008或者是更低版本vs编译的C++代码.都会在工程编译后,都会提示一条错误: C:\Program ...

  6. .NET vs2010中使用IrisSkin2.dll轻松实现winForm窗体换肤功能

    IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现winForm窗体换肤! 网上很多朋友说在VS2010中不能使用IrisSkin2.dll,我这里提供一个取巧的办法. Iri ...

  7. vs2010中使用Nunit测试c#代码结果的正确性

    本文转载自:http://blog.csdn.net/pukuimin1226/article/details/8112151 http://www.nunit.org/index.php?p=dow ...

  8. 怎样在VS2010中打开VS2012的项目

    VS2012中对C#的支持度非常好,不管是编写方便程度(不需要插件就能高亮代码及代码自动提示功能),还对MFC的一些功能优化很多. 我们可以修改两个工程文件来把VS2012的工程文件一直到VS2010 ...

  9. VS2010中如何查看DLL的导出接口

    看<VC++动态链接库(DLL)编程深入浅出>时,里面提到使用Visual C++的Depends工具可以查看动态链接库中的导出接口.对于VC6.0,VC所带的Depends软件,在VC6 ...

随机推荐

  1. centos7添加服务

    [Unit] Description=rockae Service After=network.target [Service] ExecStart=/bin/java -jar /usr/local ...

  2. Servlet入门(第一个Servlet的Web程序)

    新建maven项目,注意项目的类型 project名为ServletExample 点击Finish.建立maven项目完毕例如以下 生成后的文件夹没有java源代码文件夹.依照maven的约定,还要 ...

  3. sqlserver被锁的表以及如何解锁

    查看sqlserver被锁的表以及如何解锁   查看被锁表: select   request_session_id   spid,OBJECT_NAME(resource_associated_en ...

  4. Ubuntu下安装Apache

    Ubuntu为我们提供了 su apt-get install 命令,通过它你可以很方便地安装一些软件,这些软件是放在Ubuntu放置在各个地方的服务器上面,如果你想安装的软件是比较常见的,一般都可以 ...

  5. jffs2制作与烧写

    JFFS2全名是Journalling Flash File System Version2.最早只支持Nor Flash,自2.6版以后开始支持Nand Flash. JFFS2是Flash上应用最 ...

  6. The declared package &quot;com.dao&quot; does not match the expected package &quot;src.com.dao&quot;

    今天把项目代码上传到svn后出现例如以下错误:The declared package "com.dao" does not match the expected package ...

  7. ES6 学习笔记 (2)-- Liunx环境安装Node.js 与 搭建 Node.js 开发环境

    笔记参考来源:廖雪峰老师的javascript全栈教程 一.安装Node.js 目前Node.js的最新版本是6.2.x.首先,从Node.js官网下载对应平台的安装程序. 1.下载 选择对应的Liu ...

  8. Hibernate-基础入门案例,增删改查

    项目结构: 数据库: /* SQLyog Ultimate v12.09 (64 bit) MySQL - 5.5.53 : Database - hibernate01 ************** ...

  9. Session 的生命周期

    #region EntityMap /// <summary>        /// 实体类值的访问器,线程安全        /// </summary>        // ...

  10. 6款强大的 jQuery 网页布局创建及优化插件

    本文将为您介绍6款功能强大的jQuery插件,它们能够帮助您方便快捷地创建复杂的网络布局并进行优化. 1.UI.Layout 该插件可以创建任何你想要的UI形式:包括从简单的标题或侧边栏,到一个包含工 ...