D语言与C++做映射时需要注意的事情
注:本实验是在VisualD的ms-coff文件格式下完成的。
做了一天的D语言中extern(C++)的ABI分析,分析结果显示不是所有的C++语法都能在D语言中对应,所以在做对应时需要注意一些问题。分析数据可以找我Q:52019943要。因为有不少,这里不列出来。只给一个主要部分:
其中,C++中的class值类型与class的引用类型,无法在D语言中表示,至少目前我还没有找到办法,有办法的可以联系我,万分感谢。因为这代表着有些C++的库是不能使用D语言直接做映射调用的,而需要转为D语言可以调用的C或C++接口后,编译成中间库再给D语言调用。
本文只在用实例测试分析结果,对分析结果进行验证。
先建立VisualD工程,三个文件,一个test.cpp的C++文件,两个D语言文件main.d与test.d,如下图:
1. 测试D语言调用C++中class的值类型 (无法调用)
test.cpp
#include "stdio.h" #include <string> using namespace std; extern "C++" { class class_type{ public: int a; }; int call_test(class_type a){ return a.a + 10; } }
test.d
module test; extern(C++){ class class_type{ public: int a; }; int call_test(class_type a); }
main.d
import std.stdio; import test; int main(string[] argv) { class_type a = new class_type(); a.a = 0;
writeln(call_test(a)); readln(); return 0; }
编译在连接时失败,无法连接符号为(?call_test@@YAHPAVclass_type@@@Z) 参数类型为PAV,P表示指针,V表示class,即D语言需要调用一个class的指针类型。而C++中的代码提供的则是一个类的值类型,所以无法连接。
再来C++中call_test函数发生了什么,使用工具打开test.o文件,发现C++中call_test符号为:
(?call_test@@YAHVclass_type@@@Z)
参数类型为V,而不是PAV,这正是class的值类型所以无法连接。
结论验证,以下语法无法直接使用D语言调用:
D语言 int call_test(class_type a) C++ int call_test(class_type a)
不能调用
2. 测试D语言调用C++中class的指针类型 (可以调用,但不能在D语言中构造,需要使用@disable this(){}语句对构造函数加以要求)
第一个测中无法调用C++中class的值类型,而需要调用的则是指针类型,这个测试来做一下实验。
在第1个测试的基础上,只修改test.cpp部分,把class_type a修改为class_type* a,如下:
test.cpp
#include "stdio.h" #include <string> using namespace std; extern "C++" { class class_type{ public: int a; }; int call_test(class_type* a){ return a->a + 10; } }
编译工程成功,运行也成功,却得到了一个想不到的结果:
运行3次得到了三个不同的结果,都不是10。
这个结果说明两个问题
1)C++中的类的指针类型是可以在D语言中调用
D语言 int call_test(class_type a) C++ int call_test(class_type* a)
可以调用
2) C++中的类不能使用来自D语言中的构造,可能是因为内存结构不一样。即:C++中的类只能使用来自C++的构造。这时候才明白dlang.org中的 @disable this(){} 这句代码,用这句代码来说明C++中的类不能在D语言中进行构造。
3. 测试D语言调用C++中class的引用类型 (无法调用)
test.cpp
#include "stdio.h" #include <string> using namespace std; extern "C++" { class class_type{ public: int a; }; int call_test(class_type& a){ return a.a + 10; } }
test.d
module test; extern(C++){ class class_type{ public: int a; }; int call_test(ref class_type a); }
main.d
import std.stdio; import test; int main(string[] argv) { class_type a = new class_type(); a.a = 0; writeln(call_test(a)); readln(); return 0; }
编译在连接时失败:
出现问题,D语言中要求连接参数类型为AAPAV,即引用指值类型,class_type*&类型,无法连接。看看C++中发生了什么
C++中提供的符号为AAV类型,即值引用类型class_type&类型,所以无法连接。需要修改C++代码,再做一个测试。
D语言 int call_test(ref class_type a) C++ int call_test(class_type& a)
不能调用
4. 测试D语言调用C++中class的指针引用类型 (可以调用)
在测试3中,只需要修改test.cpp代码为:
test.cpp
#include "stdio.h" #include <string> using namespace std; extern "C++"{ class class_type{ public: int a; }; typedef class_type* abc; int call_test(abc& a){ return a->a + 10; } }
C++中不能直接使用int call_test(class_type*& a) ,编译时通不过,可以使用以上代码。编译通过。
可以运行,结果随机,原因如测试2中分析,不能在D语言中对C++的类进行构造。
D语言 int call_test(ref class_type a) C++ typedef class_type* pclass_type; int call_test(pclass_type& a)
可以调用
5. 测试D语言调用C++中class指针的指针类型 (可以调用)
test.cpp
#include "stdio.h" #include <string> using namespace std; extern "C++"{ class class_type{ public: int a; }; int call_test(class_type** a){ return (*a)->a + 10; } }
test.d
module test; extern(C++){ class class_type{ public: int a; }; int call_test(class_type* a); }
main.d
import std.stdio; import test; int main(string[] argv) { class_type a = new class_type(); a.a = 0; writeln(call_test(&a)); readln(); return 0; }
编译通过,测试过行成功。
即C++中类的指针的指针类型可以在D语言中做映射,运行结果如测试2中分析。
6. 测试D语言调用C++中struct的值类型 (直接通用)
test.cpp
#include "stdio.h" #include <string> using namespace std; extern "C++"{ struct struct_type{ public: int a; }; int call_test(struct_type a){ return a.a + 10; } }
test.d
module test; extern(C++){ struct struct_type{ public: int a; }; int call_test(struct_type a); }
main.d
import std.stdio; import test; int main(string[] argv) { struct_type a; a.a = 0; writeln(call_test(a)); readln(); return 0; }
编译通过,运行结果为10 ,即D语言中的构造C++中的struct后,传给C++调用正常,通用性相当强。
7. 测试D语言调用C++中struct的引用类型 (直接通用)
在测试6的基础上修改:
test.cpp
#include "stdio.h" #include <string> using namespace std; extern "C++"{ struct struct_type{ public: int a; }; int call_test(struct_type& a){ return a.a + 10; } }
test.d
module test; extern(C++){ struct struct_type{ public: int a; }; int call_test(ref struct_type a); }
编译通过,运行结果为10
结构的对应非常好,还有三种不做测试了,因为在使用过程中已经测试过了。
作者:宛宏南