Jac*_*lch 10 c++ d class segmentation-fault
我试图找到一种在D中使用C++类的方法.
http://www.digitalmars.com/d/2.0/cpp_interface.html
D不能调用C++特殊成员函数,反之亦然.这些包括构造函数,析构函数,转换运算符,运算符重载和分配器.
所以,我试图将这些C++函数愚蠢地转换为C风格的函数调用.这是我正在使用的证据.
class someClass {
public:
someClass();
char *whatSayYou();
};
extern "C"
{
someClass *hearMeOut();
}
Run Code Online (Sandbox Code Playgroud)
#include "helper.h"
someClass::someClass()
{
}
char *someClass::whatSayYou()
{
return "Everything is gravy";
}
someClass *hearMeOut()
{
return new someClass;
}
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
以下是我如何遵守它.
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++
Run Code Online (Sandbox Code Playgroud)
一旦调用该方法,我就会出现分段错误.
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 ()
Run Code Online (Sandbox Code Playgroud)
您的C++版本按值返回.
您的D版本希望它通过引用返回.
从本质上讲,您的C++版本在堆栈上粘贴了someClass的副本.D认为C++会将指针放在堆栈上.它试图将someClass的副本解释为指针,并发生不好的事情.
问题是在D中,类和接口总是通过引用返回.C++按值返回所有内容,除非您指明它是引用或指针.
因此你需要这个:
someClass * hearMeOut() { return new someClass; }
Run Code Online (Sandbox Code Playgroud)
别忘了稍后删除它.
您还没有公开 C 接口。您的函数仍然返回 C++ 类,而不是 C 可以识别的内容。将您的类公开为void *s 。例如:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这将使您的类可以由 D 使用,也可以由 C(以及与 C 绑定的所有其他语言)使用。