ライブラリの基礎 - C++DLL

提供:MochiuWiki : SUSE, EC, PCB
2019年10月31日 (木) 13:14時点における192.168.1.17による版 (→‎サンプルコード)
ナビゲーションに移動 検索に移動

概要

C# EXEからC++ DLLへ様々なデータ型の変数を渡したいときがある。

例えば、C++ DLLから次のような関数がエクスポートされているとする。

 void WINAPI ConvertToShort(char *pstr, short *pret);


上記の関数において、C# EXEから使用するときは、char*型は文字列なのでstring型を渡す。
short*型はIntPtr型を渡す。(IntPtr型は汎用ポインタを表す型であり、void*型とほぼ同義)

但し、C#は厳しい型付け言語なので、曖昧さを解決するために変換メソッドを経由する必要がある。
具体的には、IntPtr型の変数にMarshal.AllocHGlobal関数で必要なサイズのメモリを確保して、それをC++ DLLに渡した後、
Marshal.ReadInt16関数(型によって異なる)等で変換した後、確保したメモリをMarshal.FreeHGlobal関数で解放するというプロセスを経る必要がある。


サンプルコード

下記に、C++ DLLを呼ぶC# EXEのソースコードを記載する。

 // DllImportを使用するために必要
 using System.Runtime.InteropServices;
 
 [DllImport("DrsUtil.dll", EntryPoint = "ConvertToShort")]
 extern static void _ConvertToShort(string pstr, IntPtr pret); //呼び出し元の名前変えちゃう
 
 public static short ConvertToShort(string str)
 {
    IntPtr buffer = new IntPtr();
    buffer = Marshal.AllocHGlobal(2);		// 2バイトのメモリ確保
    _ConvertToShort(str, buffer);		// C++/DLLの関数を呼ぶ
    short sval = Marshal.ReadInt16(buffer);	// 変換
    Marshal.FreeHGlobal(buffer);		// メモリ開放
    return sval;
 }


IntPtr型の変数は様々なものが入るので、例えば、構造体を取得することも可能だが、C# EXEで構造体を定義しなければいけない。
WindowsのDLL(Win32 API)と.NET Frameworkでは型の管理方法が違うため、実際には型の相互変換(マーシャリング)が行われる。
尚、BOOL型の実体はLONG型と同じなので、boolの代わりにintを指定することも可能である。

表1. Win32 APIでの型名と対応するC#の型
APIの型名
(括弧内は対応するC言語の型)
対応するC#の型
(括弧内は.NET Frameworkでの型名)
備考
HANDLE (void *) System.IntPtr
System.UIntPtr
x86は4バイト
x64は8バイト
BYTE (unsigned char) byte (System.Byte)
SHORT (short) short (System.Int16)
WORD (unsigned short) ushort (System.UInt16)
INT (int)
LONG (long)
int (System.Int32)
UINT (unsigned int)
DWORD, ULONG (unsigned long)
uint (System.UInt32)
BOOL (long) bool (System.Boolean)
CHAR (char) 文字を渡すとき
char (System.Char)
文字を受け取るとき
StringBuilder
WCHAR(wchar_t) 文字を渡すとき
char (System.Char)
文字を受け取るとき
StringBuilder
LPSTR (char *, char[])
LPWSTR (wchar_t *, wchar_t[])
文字を渡すとき
string (System.String)
文字を受け取るとき
System.Text.StringBuilder
LPCSTR (const char *, const char[])
LPCWSTR (const wchar_t *, const wchar_t[])
文字を渡すとき
string (System.String)
文字を受け取るとき
System.Text.StringBuilder
FLOAT (float) float (System.Single)
DOUBLE (double) double (System.Double)