D语言与C++做映射时需要注意的事情

    注:本实验是在VisualD的ms-coff文件格式下完成的。

    做了一天的D语言中extern(C++)的ABI分析,分析结果显示不是所有的C++语法都能在D语言中对应,所以在做对应时需要注意一些问题。分析数据可以找我Q:52019943要。因为有不少,这里不列出来。只给一个主要部分:

image       其中,C++中的class值类型与class的引用类型,无法在D语言中表示,至少目前我还没有找到办法,有办法的可以联系我,万分感谢。因为这代表着有些C++的库是不能使用D语言直接做映射调用的,而需要转为D语言可以调用的C或C++接口后,编译成中间库再给D语言调用。

      本文只在用实例测试分析结果,对分析结果进行验证。

      先建立VisualD工程,三个文件,一个test.cpp的C++文件,两个D语言文件main.d与test.d,如下图:

image     设置工程属性:

image

       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++中的代码提供的则是一个类的值类型,所以无法连接。

image

再来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;
    }
}

          编译工程成功,运行也成功,却得到了一个想不到的结果:

image image image

          运行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;
}

      编译在连接时失败:

image    

      出现问题,D语言中要求连接参数类型为AAPAV,即引用指值类型,class_type*&类型,无法连接。看看C++中发生了什么

image      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) ,编译时通不过,可以使用以上代码。编译通过。

image     可以运行,结果随机,原因如测试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;
}

       编译通过,测试过行成功。

image      即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;
}

image      编译通过,运行结果为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

image      结构的对应非常好,还有三种不做测试了,因为在使用过程中已经测试过了。

作者:宛宏南

原文地址:https://www.cnblogs.com/wanhongnan/p/5780761.html