C++でライブラリー(DLL)を作り、pythonなどから利用する方法について連載します。
1. C++でライブラリーを作る Linux編
2. pythonからC++のライブラリーを利用する Linux編
3. C++でライブラリー(DLL)を作る Windows編
4. pythonからC++のライブラリー(DLL)を利用する Windows編
5. C#からC++のライブラリー(DLL)を利用する
6. python・C#とC++間で複素数を受け渡す
このページではC#から上記3.にてC++で作成したDLLを利用する方法について説明します。
概要
C#では、DLLからインポートする関数を次のように定義します。
[DllImport("LocalLib.dll")]
static extern int LLibSum(int nInA, int nInB);
ポインターはC#ではrefを使用します。
C#からCへ渡す文字列は System.Text.StringBuilder を使用します。
CからC#へ渡す文字列はC#で受け取った後にToString()で変換します。
DLLの構造体で使用している固定長の文字列は、C#ではMarshalAsを使って定義します。
注意点として、C#のプラットフォームにAnyCPUを選択すると、ビルドオプションの「32ビットを選ぶ」がデフォルトはチェックされた状態なので、64ビットのDLLが利用出来ません。チェックを外してビルドして下さい。
サンプルコード
using System.Runtime.InteropServices;
namespace CallLibCs
{
internal class Program
{
struct tagLibParameter {
public double dInA;
public double dInB;
public double dOut;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string sData;
}
[DllImport("LocalLib.dll")]
static extern int LLibSum(int nInA, int nInB);
[DllImport("LocalLib.dll")]
static extern int LLibCalcX10(ref double dpOut, ref double dpIn, int nInLen);
[DllImport("LocalLib.dll")]
static extern int LLibTxRxMessage(System.Text.StringBuilder bpOut, System.Text.StringBuilder bpIn, int nInLen);
[DllImport("LocalLib.dll")]
static extern int LLibInOutStr(ref tagLibParameter sp);
static void Main(string[] args)
{
int nA, nB, nSum;
nA = 1;
nB = 2;
//---------------------
nSum = LLibSum(nA, nB);
//---------------------
System.Console.Write("{0} + {1} = {2}\n", nA, nB, nSum);
//================================================================
int nLen = 3;
double[] dsOut = new double[nLen];
double[] dsIn = new double[nLen];
dsIn[0] = 1.1;
dsIn[1] = 2.2;
dsIn[2] = 3.3;
//----------------------------------------------------------
LLibCalcX10(ref dsOut[0], ref dsIn[0], nLen);
//----------------------------------------------------------
System.Console.Write("in[{0:0.0} {1:0.0} {2:0.0}] out[{3:0.0} {4:0.0} {5:0.0}]\n",
(dsIn[0]), (dsIn[1]), (dsIn[2]),
(dsOut[0]), (dsOut[1]), (dsOut[2]));
//================================================================
System.Text.StringBuilder sRxBuf = new System.Text.StringBuilder(256);
System.Text.StringBuilder sTxBuf = new System.Text.StringBuilder(64);
sTxBuf.Append("App->DLL: Hello !");
LLibTxRxMessage(sRxBuf, sTxBuf, 256);
System.Console.Write("{0}\n", (sRxBuf.ToString()));
//================================================================
tagLibParameter LP = new tagLibParameter();
(LP.dInA) = 1.1;
(LP.dInB) = 2.2;
//-------------------
LLibInOutStr(ref LP);
//-------------------
System.Console.Write("{0:0.0} + {1:0.0} = {2:0.0} [{3}]\n",
(LP.dInA), (LP.dInB), (LP.dOut), (LP.sData.ToString()));
}
}
}
実行例
C#でビルドした実行ファイル(CallLib.exe)と冒頭3.にて作成したLocalLib.dllを同じディレクトリーに置いて実行して下さい。
C#とDLLの間で、変数、配列、文字列、構造体の双方向のやりとりが出来ています。
冒頭3.のC++および4.のpythonで作った呼び出し側のサンプルコード実行時と同じ結果です。
D:\>CallLib.exe
start DLL
1 + 2 = 3
in[1.1 2.2 3.3] out[11.0 22.0 33.0]
DLL->App: Hi ! rcvd[App->DLL: Hello !]
1.1 + 2.2 = 3.3 [2025 11/18 16:48:57 071]
end DLL