使用 C++ D类

发布于 2024-10-05 05:44:57 字数 2060 浏览 2 评论 0原文

我正在尝试找到一种在 D 中使用 C++ 类的方法。

http://www.digitalmars .com/d/2.0/cpp_interface.html

D 不能调用 C++ 特殊成员函数,反之亦然。其中包括构造函数、析构函数、转换运算符、运算符重载和分配器。

因此,我试图将这些 C++ 函数简化为 C 风格的函数调用。这是我正在使用的证据。

helper.h

class someClass {
    public:
        someClass();
        char *whatSayYou();
};

extern "C"
{
    someClass *hearMeOut();
}

helper.cpp

#include "helper.h"

someClass::someClass()
{

}

char *someClass::whatSayYou()
{
    return "Everything is gravy";
}


someClass *hearMeOut()
{
    return new someClass;
}

main.d

import std.stdio;

int main(string[] args)
{
    someClass *awesomeExample = hearMeOut();
    char *shoutoutToTheWorld = awesomeExample.whatSayYou();
    writefln(std.string.toString(shoutoutToTheWorld));
    return 0;
}


extern (C++)
{
    interface someClass
    {
        char *whatSayYou();
    }

    someClass *hearMeOut();
}

这是我的编译方法。

g++-4.3 -c -I code/dg3d_helper -I /usr/local/include/ -o code/dg3d_helper/helper.o code/dg3d_helper/helper.cpp
code/dg3d_helper/helper.cpp: In member function ‘char* someClass::whatSayYou()’:
code/dg3d_helper/helper.cpp:19: warning: deprecated conversion from string constant to ‘char*’
gdc-4.3 -g -c -I code/ -o code/main.o code/main.d
gdc-4.3 -g -I code/ -o main code/dg3d_helper/helper.o code/main.o -lstdc++

一旦调用该方法,我就会遇到分段错误。

Program received signal SIGSEGV, Segmentation fault.
0x0000000000402fa0 in _Dmain (args=...) at code/main.d:7
7       char *shoutoutToTheWorld = awesomeExample.whatSayYou();
(gdb) bt
#0  0x0000000000402fa0 in _Dmain (args=...) at code/main.d:7
#1  0x000000000041b1aa in _D9dgccmain211_d_run_mainUiPPaPUAAaZiZi2goMFZv ()
#2  0x000000000041b235 in _d_run_main ()
#3  0x00002aaaab8cfc4d in __libc_start_main () from /lib/libc.so.6
#4  0x0000000000402d59 in _start ()

I am trying to find a way to use C++ classes in D.

http://www.digitalmars.com/d/2.0/cpp_interface.html

D cannot call C++ special member functions, and vice versa. These include constructors, destructors, conversion operators, operator overloading, and allocators.

So, I am attempting to dumb down these C++ functions to C style function calls. Here is the proof I am working with.

helper.h

class someClass {
    public:
        someClass();
        char *whatSayYou();
};

extern "C"
{
    someClass *hearMeOut();
}

helper.cpp

#include "helper.h"

someClass::someClass()
{

}

char *someClass::whatSayYou()
{
    return "Everything is gravy";
}


someClass *hearMeOut()
{
    return new someClass;
}

main.d

import std.stdio;

int main(string[] args)
{
    someClass *awesomeExample = hearMeOut();
    char *shoutoutToTheWorld = awesomeExample.whatSayYou();
    writefln(std.string.toString(shoutoutToTheWorld));
    return 0;
}


extern (C++)
{
    interface someClass
    {
        char *whatSayYou();
    }

    someClass *hearMeOut();
}

And here is how I complied it.

g++-4.3 -c -I code/dg3d_helper -I /usr/local/include/ -o code/dg3d_helper/helper.o code/dg3d_helper/helper.cpp
code/dg3d_helper/helper.cpp: In member function ‘char* someClass::whatSayYou()’:
code/dg3d_helper/helper.cpp:19: warning: deprecated conversion from string constant to ‘char*’
gdc-4.3 -g -c -I code/ -o code/main.o code/main.d
gdc-4.3 -g -I code/ -o main code/dg3d_helper/helper.o code/main.o -lstdc++

And I get a segmentation fault as soon as the method is called.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000402fa0 in _Dmain (args=...) at code/main.d:7
7       char *shoutoutToTheWorld = awesomeExample.whatSayYou();
(gdb) bt
#0  0x0000000000402fa0 in _Dmain (args=...) at code/main.d:7
#1  0x000000000041b1aa in _D9dgccmain211_d_run_mainUiPPaPUAAaZiZi2goMFZv ()
#2  0x000000000041b235 in _d_run_main ()
#3  0x00002aaaab8cfc4d in __libc_start_main () from /lib/libc.so.6
#4  0x0000000000402d59 in _start ()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

趁年轻赶紧闹 2024-10-12 05:44:57

您的 C++ 版本按值返回。

您的 D 版本期望它通过引用返回。

本质上,您的 C++ 版本在堆栈上粘贴了 someClass 的副本。 D 认为 C++ 将在堆栈上放置一个指针。它试图将 someClass 的副本解释为指针,但糟糕的事情发生了。

问题是在 D 中,类和接口总是通过引用返回。 C++ 按值返回所有内容,除非您指示它是引用或指针。

因此你需要这个:

someClass * hearMeOut() { return new someClass; }

不要忘记稍后删除它。

Your C++ version returns by value.

Your D version expects it to return by reference.

Essentially, your C++ version sticks a copy of someClass on the stack. D thinks that C++ will have put a pointer on the stack. It tries to interpret the copy of someClass as a pointer, and bad things happen.

The problem is that in D, classes and interfaces are always returned by reference. C++ returns everything by value unless you indicate that its either a reference or a pointer.

Thus you need this:

someClass * hearMeOut() { return new someClass; }

Don't forget to delete it later.

眼藏柔 2024-10-12 05:44:57

您还没有公开 C 接口。您的函数仍然返回 C++ 类,而不是 C 可识别的内容。将您的类公开为 void *。例如:

class MyClass
{
//private members
public:
//public members
    int MyMethod(int argument) const;
    virtual float MyVirtualMethod();
    virtual ~MyClass() {}
};

class MySecondClass : public MyClass
{
public:
    virtual float MyVirtualMethod();
    int MyMethod2(int argument) const;
};

extern "C" {
    void * CreateMyClass()
    {
        return static_cast<void *>(new(std::nothrow) MyClass);
    }

    void * CreateMySecondClass()
    {
        //Note the cast to the base class first (This is needed
        //because it might actually change the position of the pointer,
        //which would not be automatically adjusted later)
        return static_cast<void *>(static_cast<MyClass *>(new(std::nothrow) MySecondClass));
    }

    int CallMyClassMethod(void * thisMember, int argument)
    {
        return static_cast<MyClass *>(thisMember)->MyMethod(argument);
    }

    float CallMyVirtualMethod(void * thisMember)
    {
        return static_cast<MyClass *>(thisMember)->MyVirtualMethod();
    }

    int CallMyMethod2(void thisMember, int argument)
    {
        MyClass * convertedToMyClass = static_cast<MyClass *>(thisMember);
        MySecondClass * asSecondClass = dynamic_cast<MySecondClass *>(convertedToMyClass);
        if (!asSecondClass)
        {
            //Return error (thisMember not an instance of MySecondClass)
        }
        else
        {
            return asSecondClass->MyMethod2(argument);
        }
    }

    void DestroyMyClass(void * classMember)
    {
        delete static_cast<MyClass *>(classMember);
    }
}

这将使您的类可以由 D 使用,也可以由 C(以及绑定到 C 的所有其他语言)使用。

You've not exposed a C interface. You still have your function returning a C++ class rather than something recognizable by C. Expose your class as void *s instead. For example:

class MyClass
{
//private members
public:
//public members
    int MyMethod(int argument) const;
    virtual float MyVirtualMethod();
    virtual ~MyClass() {}
};

class MySecondClass : public MyClass
{
public:
    virtual float MyVirtualMethod();
    int MyMethod2(int argument) const;
};

extern "C" {
    void * CreateMyClass()
    {
        return static_cast<void *>(new(std::nothrow) MyClass);
    }

    void * CreateMySecondClass()
    {
        //Note the cast to the base class first (This is needed
        //because it might actually change the position of the pointer,
        //which would not be automatically adjusted later)
        return static_cast<void *>(static_cast<MyClass *>(new(std::nothrow) MySecondClass));
    }

    int CallMyClassMethod(void * thisMember, int argument)
    {
        return static_cast<MyClass *>(thisMember)->MyMethod(argument);
    }

    float CallMyVirtualMethod(void * thisMember)
    {
        return static_cast<MyClass *>(thisMember)->MyVirtualMethod();
    }

    int CallMyMethod2(void thisMember, int argument)
    {
        MyClass * convertedToMyClass = static_cast<MyClass *>(thisMember);
        MySecondClass * asSecondClass = dynamic_cast<MySecondClass *>(convertedToMyClass);
        if (!asSecondClass)
        {
            //Return error (thisMember not an instance of MySecondClass)
        }
        else
        {
            return asSecondClass->MyMethod2(argument);
        }
    }

    void DestroyMyClass(void * classMember)
    {
        delete static_cast<MyClass *>(classMember);
    }
}

This will make your class usable by D, but also by C (and every other language that binds to C) as well.

一片旧的回忆 2024-10-12 05:44:57

D 只能使用接口技巧调用虚拟 C++ 方法。

此外,您告诉 DhearMeOut() 使用 C++ 调用约定,而 C++ 它具有 C 调用约定。如果我错了,请纠正我,但这也会产生问题。

在我看来,这种方式与 C++ 的接口实际上仅限于调用简单的函数,因为在大多数 C++ 库中,您总是有非虚拟方法、运算符以及类中的其他任何内容,更不用说 D 也无法处理的命名空间了。

D SFML 按照 Billy 描述的方式进行操作。维护 C 包装器和 D 包装器是一项繁琐的工作。
应该使用一些(半)自动方法,例如 SWIG,那么您还可以获得很好的跨语言多态性。

D can only call virtual C++ methods with the interface trick.

Furthermore you tell D hearMeOut() used C++ calling convention and C++ it has C calling conv. Correct me if I'm wrong, but this should yield problems too.

Imo interfacing with C++ this way is practically limited to calling simple functions since in most C++ libraries you always have non-virtual methods, operators and whatever else in classes, not to mention namespaces which D can't cope with as well.

D SFML does it the way Billy described. It's a tedious job to maintain the C wrapper plus the D wrapper.
Some (semi-)automatic approach like SWIG should be used, then you also get nice cross-language polymorphism.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文