【问题标题】:Using C++ constructors from D使用 D 中的 C++ 构造函数
【发布时间】:2017-09-10 15:18:52
【问题描述】:

在 D wiki 上有一个关于 C++ 接口的页面 - https://dlang.org/spec/cpp_interface.html

它说您可以链接到 C++ 代码,但由于对象的生命周期问题,不能链接到特殊方法,包括构造函数、析构函数和运算符重载。建议使用包装器(并在 C/C++ 端构造对象)或使用 D 重新实现构造函数。这两种方法都需要完成大量工作,有时可能是不可能的。如果你想在你的 D 程序中使用一些 C++ 库,这感觉是一个巨大的问题:例如,你想使用 Qt 的 QML 并且可以定义需要的类以与 extern(C++)... 一起使用,但是你坚持使用构造函数和大量包装器(就像 dqml 项目一样)或移植的代码。

但是有一种方法看起来很有效。简单例子:

//class.h

class MyTestClass {
    int x = 0;
    int z = 0;

public:
    MyTestClass(int y);
    int getX();
    int getZ();
};

//class.cpp

#include "class.h"

MyTestClass::MyTestClass(int y) {
    x = y;
};

int MyTestClass::getX() {
    return x;
};

int MyTestClass::getZ() {
    return z;
};

我将此代码编译成class.lib,以便稍后在此D程序中链接和使用:

//main.d
import std.stdio;

extern(C++) {
    class MyTestClass {
        pragma(mangle, "??0MyTestClass@@QEAA@H@Z") this(int y);
        final int getX();
        final int getZ();
    }
}

void main()
{
    int checks = 0;
    int goal = 1_000_000_000;
    foreach (int i; 0 .. goal) {
        MyTestClass test = new MyTestClass(5);
        if (test.getX() == 5 && test.getZ() == 0) checks++;
    }
    writeln(checks, " successfull from ", goal);
    readln();
}

通过这种方式,我手动将 D 构造函数名称更改为 C++ 之一,因为我不知道让编译器自己执行此操作。然后我只是在循环中创建和检查对象,并通过任务管理器观察进程内存使用情况。每次检查都很好(所以z初始化器和从构造函数中设置x都正确调用)并且我没有看到内存泄漏(所以看起来D在十亿次迭代中创建和销毁对象没有任何问题)。

问题是:以这种方式调用构造函数(和析构函数)是否存在任何隐藏问题?在更困难的条件或类似情况下导致程序崩溃的任何内存问题?或者在某些情况下可能会出现一些奇怪的行为?

【问题讨论】:

    标签: c++ d


    【解决方案1】:

    问题在于 C++ 和 D 的构造函数和析构函数以不同的顺序在不同的时间做类似的事情。

    • 在调用 D 构造函数之前初始化内存。 C++ 构造函数自行清除内存。
    • 当对象超出范围时调用 C++ 析构函数。在 D 中,垃圾收集器调用析构函数。

    当您开始在 C++ 和 D 之间混合类层次结构时,这很容易导致麻烦。

    但在您的示例的简单情况下(仅调用 ctor,没有继承混合)应该没有问题。

    【讨论】:

      猜你喜欢
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多