使用 C++ D类
我正在尝试找到一种在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的 C++ 版本按值返回。
您的 D 版本期望它通过引用返回。
本质上,您的 C++ 版本在堆栈上粘贴了 someClass 的副本。 D 认为 C++ 将在堆栈上放置一个指针。它试图将 someClass 的副本解释为指针,但糟糕的事情发生了。
问题是在 D 中,类和接口总是通过引用返回。 C++ 按值返回所有内容,除非您指示它是引用或指针。
因此你需要这个:
不要忘记稍后删除它。
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:
Don't forget to delete it later.
您还没有公开 C 接口。您的函数仍然返回 C++ 类,而不是 C 可识别的内容。将您的类公开为
void *
。例如:这将使您的类可以由 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:This will make your class usable by D, but also by C (and every other language that binds to C) as well.
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.