C++ で作成した DLL をD言語のプログラムから呼び出す手順

D言語のプログラム(.d ファイル)から DLL を呼び出すやり方には、暗黙的リンクと明示的リンクの二つのやり方があります。
既に、C/C++ で作成した .dll ファイルがあれば、DLL を呼び出す手順は次のようになります。

暗黙的リンクの場合
1. implib で .dll ファイルから .lib ファイルを生成する。
2. 暗黙的リンク用の .d ファイルを作成する。(.d ファイルの中でリンクする .dll のファイル名を明示しません)
3. dmd で .d ファイルと .lib ファイルから .exe ファイルをビルドする。
4. .exe ファイルと .dll ファイルを同じフォルダに入れて .exe ファイルを実行すると .dll ファイルが呼び出される。
明示的リンクの場合
1. 明示的リンク用の .d ファイルを作成する。(.d ファイルの中でリンクする .dll のファイル名を明示します)
2. dmd で .d ファイルから .exe ファイルをビルドする。
3. .exe ファイルと .dll ファイルを同じフォルダに入れて .exe ファイルを実行すると .dll ファイルが呼び出される。

詳細は、「clang++ による DLL (ダイナミックリンクライブラリ) のビルド」の「.lib ファイルのビルド」以降の記事をご覧ください。

尚、最初に .dll ファイルと .h ファイルがある場合は、htod で .h ファイルを .d ファイルに変換し、DLL をリンクする .d ファイルの中で import し、dmd でビルドします。例えば、array.dll と array.h がある場合は、まず、htod で array.h を array.d に変換します。

array.h

#ifndef ARRAY_H
#define ARRAY_H

void setArray(double*, int, double);
double getArray(double*, int);

#endif

h2d.bat

set path=D:\htod
htod array.h -o array.d

array.d

/* Converted to D from array.h by htod */
module array;
//C     #ifndef ARRAY_H
//C     #define ARRAY_H

//C     void setArray(double*, int, double);
extern (C):
void  setArray(double *, int , double );
//C     double getArray(double*, int);
double  getArray(double *, int );

//C     #endif

そして、implicit.d の中で array.d を import します。

implicit.d

import array;
import std.stdio;

void main() {
  uint n = 10;
  auto a = new double[](n);
  a[] = 0;
  foreach (i; 0..a.length) {
    setArray(a.ptr, i, cast(double)i);
    writefln("a[%d] = %.5f", i, getArray(a.ptr, i));
  }
}

implicit.d、array.d、array.lib を同じフォルダに入れて implicit.bat を実行すれば、caller.exe がビルドされます。

implicit.bat

set path=D:\dmd2\windows\bin
dmd -O -release implicit.d array.lib -ofcaller.exe

後は、caller.exe と array.dll を同じフォルダに入れて実行するだけです。


現状では D言語の double[] 型の1次元配列 a を C++ の double* 型引数に a.ptr で渡すことはできたのですが、double[][] 型の2次元配列を double** 型引数に渡すことはできませんでした。そのため、多次元配列を扱う場合は、一旦1次元配列に変換する必要がありそうです。
また、D言語の string 型データを C++ の stiring 型引数に渡すのもうまくいきませんでした。文字列に関しては、<iostream> を使って、単に文字列を標準出力するプログラムも実行時にエラーが発生するので、Clang 側の問題かもしれません。

結論:
暗黙的リンクは、同じ言語の関数を呼び出すのと同じような感覚で、異なる言語の関数を呼び出せるので、お薦めです!

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中