和 类似, importcpp 编译指示一般可以用于引入 C++ 方法或C++符号。 生成的代码会使用C++方法调用的语法: obj->method(arg) 。
结合 header 和 emit 编译指示,这允许与C++库的 草率 接口:
需要告诉编译器生成C++(命令 cpp )才能使其工作。 当编译器发射C++代码时,会定义条件符号 cpp 。
草率接口 示例使用 .emit 来生成 using namespace 声明。 通过 命名空间::标识符 符号来引用导入的名称通常要好得多:
- type
- IrrlichtDeviceObj {.header: irr,
- importcpp: "irr::IrrlichtDevice".} = object
枚举Importcpp
当 importcpp 应用于枚举类型时,数字枚举值用C++枚举类型注释, 像这个示例: ((TheCppEnum)(3)) 。 (事实证明这是实现它的最简单方法。)
请注意,procs的 importcpp 变体使用了一种有点神秘的模式语言,以获得最大的灵活性:
符号 @ 被剩下的参数替换,用逗号分隔。示例:
- proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "#.CppMethod(@)".}
- var x: ptr CppObj
- cppMethod(x[], 1, 2, 3)
生成:
作为一个特殊的规则来保持与旧版本的 importcpp 编译指示的向后兼容性,如果没有特殊的模式字符(任何一个 #'@ ),那么认为是C++的点或箭头符号,所以上面的例子也可以写成:
- proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "CppMethod".}
请注意,模式语言自然也涵盖了C++的运算符重载功能:
- 上标点 ' 后跟0..9范围的整数 i 被第i个形参类型替换。 第0位是结果类型。这可以用于将类型传递给C++函数模板。 在 ' 和数字之间可以使用星号来获得该类型的基类型。 (所以它从类型中“拿走了一颗星”; T * 变为 T 。) 可以使用两颗星来获取元素类型的元素类型等。示例:
- type Input {.importcpp: "System::Input".} = object
- proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()", nodecl.}
- let x: ptr Input = getSubsystem[Input]()
生成:
- x = SystemManager::getSubsystem<System::Input>()
- #@ 是一个支持 cnew 操作的特例。 这是必需的,以便直接内联调用表达式,而无需通过临时位置。 这只是为了规避当前代码生成器的限制。
例如,C++的 new 运算符可以像这样“导入”:
- proc cnew*[T](x: T): ptr T {.importcpp: "(new '*0#@)", nodecl.}
- # 'Foo'构造函数:
- proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)".}
- let x = cnew constructFoo(3, 4)
但是,根据用例, 也可以这样包装:
封装构造函数
有时候C++类有一个私有的复制构造函数,因此不能生成像 Class c = Class(1,2); 这样的代码,而是 Class c(1,2); 。 为此,包含C ++构造函数的Nim proc需要使用 构造函数 编译器。 这个编译指示也有助于生成更快的C++代码,因为构造然后不会调用复制构造函数:
- # 更好的'Foo'构建函数:
- proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)", constructor.}
封装destruct由于Nim直接生成C++,所以任何析构函数都由C++编译器在作用域出口处隐式调用。 这意味着通常人们可以完全没有封装析构函数! 但是当需要显式调用它时,需要将其封装起来。 模式语言提供了所需的一切:
- proc destroyFoo(this: var Foo) {.importcpp: "#.~Foo()".}
对象的Importcpp
泛型 importcpp 的对象映射成C++模板。这意味着您可以轻松导入C++的模板,而无需对象类型的模式语言:
- type
- StdMap {.importcpp: "std::map", header: "<map>".} [K, V] = object
- proc `[]=`[K, V](this: var StdMap[K, V]; key: K; val: V) {.
- importcpp: "#[#] = #", header: "<map>".}
- var x: StdMap[cint, cdouble]
- x[6] = 91.4
生成:
- std::map<int, double> x;
- x[6] = 91.4;
- 如果需要更精确的控制, 上标点 ' 可以用在提供的模式里标志泛型类型的具体类型参数。 更多细节,见过程模式中的上标点操作符。
Produces:
- std::vector<int>::iterator x;