dlang 如何将 Magick++ class 从 C++ 导入 D

dlang How to import a Magick++ class from C++ into D

如何从 D 中的库导入 class?
我做错了什么吗?我已经成功地通过库从 dll 导入了函数,但从来没有 class.

尝试从 .lib 导入 class 出现这些错误:

main.obj : error LNK2019: unresolved external symbol "public: void __cdecl Magick::Image::write(char const *)" (?write@Image@Magick@@QEAAXPEBD@Z) referenced in function _Dmain
main.exe : fatal error LNK1120: 1 unresolved externals

这是我尝试导入 class 的方式,我认为这些是正确的定义,但可能是错误的:

pragma(lib, "library.lib");
extern (C++){
    Image createImage(const(char)*);
    void deleteImage(ref Image d);
}

pragma(lib, "C:/Program Files/ImageMagick-7.0.5-Q16/lib/CORE_RL_Magick++_.lib");
pragma(lib, "C:/Program Files/ImageMagick-7.0.5-Q16/lib/CORE_RL_MagickCore_.lib");
pragma(lib, "C:/Program Files/ImageMagick-7.0.5-Q16/lib/CORE_RL_MagickWand_.lib");
extern (C++,Magick){
    void InitializeMagick(const(char)*);
    //void InitializeMagick(const(char)* __ptr64);
    class Image{
        //There are errors trying to import any constructor or function
        //this();
        //this(const(char)*);
        final void write(const(char)*);
    }
}

int main(string[] args){
    Magick.InitializeMagick("");
    Magick.Image img = createImage("screenshot:");
    img.write("file.jpg"); //linking problems after adding this line
    return 0;
}

这是我要在 D:

中导入的函数
void Image::write(const string &filename);

class Image 的构造函数和 write 方法都采用 std::string 而不是 char*。您没有收到来自 createImage 的投诉,因为它在 cpp 端将 char* 转换为 std::string,但是您收到来自 Image.write 的投诉,因为 D 编译器无法转换 char*std::string.
您需要向 d 编译器传授有关 std::string 的知识,并以与 Magick::Image.
相同的方式围绕 std::string 进行包装 如果你在堆的 cpp 端创建 std::string 并且只传递一个指针,你可以不用太多样板文件就可以摆脱它。这是一个例子:

// wrapper.cpp
#include <Magick++.h>
#include <string>

Magick::Image* createImage(const std::string &imageSpec_)
{
    return new Magick::Image(imageSpec_);
}

void deleteImage(Magick::Image *&image)
{
    delete image;
    image = NULL;
}

std::string* createCppString(const char *s)
{
    return new std::string(s);
}

void deleteCppString(std::string *&sp)
{
    delete sp;
    sp = NULL;
}
// imm.d
pragma(lib, "wrapper.lib");
extern (C++, std)
{
    // std::string boilerplate
    struct allocator(T);
    struct char_traits(CharT);
    struct basic_string(CharT, Traits=char_traits!CharT, Allocator=allocator!CharT);
    alias string = basic_string!char;
}

pragma(lib, "C:/Program Files/ImageMagick-7.0.5-Q16/lib/CORE_RL_Magick++_.lib");
pragma(lib, "C:/Program Files/ImageMagick-7.0.5-Q16/lib/CORE_RL_MagickCore_.lib");
pragma(lib, "C:/Program Files/ImageMagick-7.0.5-Q16/lib/CORE_RL_MagickWand_.lib");extern (C++, Magick)
{
    void InitializeMagick(const(char)*);
    class Image
    {
        @disable this();
        final void write(ref const(std.string));
    }
}

extern (C++)
{
    Magick.Image createImage(ref const(std.string));
    void deleteImage(ref Magick.Image);
    std.string* createCppString(const(char)*);
    void deleteCppString(ref std.string*);
}

void main() {
    Magick.InitializeMagick("");

    auto imgsrc = "screenshot:".createCppString;
    scope(exit) deleteCppString(imgsrc);

    Magick.Image img = createImage(*imgsrc);
    scope(exit) deleteImage(img);

    auto filename = "file.jpg".createCppString;
    scope(exit) deleteCppString(filename);

    img.write(*filename);
}

但是如果你想在堆栈上创建 std::string(在 cpp 端)并通过 vale 传递它而不是传递指针你需要更多样板,你需要填写base_string 的字段

struct basic_string(CharT, Traits=char_traits!CharT, Allocator=allocator!CharT);
{
    // fill in the fields ...
}

这是最好的方法,但祝你好运(base_string.h 不是很友好),但你可以让工具为你完成艰苦的工作,例如 htod