経緯
C#で作成したDLLをC++で呼び出そうとした場合、引数の受け渡しの部分で少しはまったので、まとめておきます。
DLLと呼び出し側の構成について
引数の型によって呼び出す構成が変わります。
引数の型 | データ | 渡し方 |
---|---|---|
プリミティブ型 | 数値 (固定の)文字列 論理値 null undefined IntPtr |
そのまま受け渡す事が可能 |
オブジェクト型 | (可変の)文字列など | IntPtrでポインタとして渡し、 受け取り後に変換 |
上述した通り、可変の文字列などは、普通の関数のように引数を受け渡す事ができない(もしかしたらできるかも・・・)ため、一旦ポインタで渡し、受け取り側で変換することが必要です。
プリミティブ型の引数の受け渡し方
DLLでの引数の受け取り方
ポインタ型の引数を受け取り、Marshal.PtrToStringAuto
でstring型
に変換します。
[DllExport]
public static bool hoGE(int iTmp)
{
・・・//普通にiTmpを使える。
}
呼び出し側の引数の渡し方
今回は以下のようにヘッダーを作成しました。
クラス内に関数ポインタ型の変数を宣言し、コンストラクタで変数に関数のポインタを格納します。
auto dll = ::LoadLibrary("EM.dll");
typedef bool (*HOGE)(int);
class EM
{
public:
EM();
~EM();
HOGE hoge;
};
EM::EM()
{
hoge = reinterpret_cast<HOGE>(::GetProcAddress(dll, "hoGE"));
}
EM::~EM()
{
if (dll)
::FreeLibrary(dll);
}
hogeの引数の型がint
なので、プリミティブ型であり、直接受け渡すことが可能です。
EM EMD;
void Check()
{
int Tmp = 25;
EMD.hoge(Tmp);
・・・
}
プリミティブ型での直接受け渡し時に注意すること
C#とC++の型の違いに注意してください。
今回、自分がはまったのが、long型
※の受け渡しでした。
型名は同じなのに、C#とC++でバイト数が異なるため、意図していない値になっていました。
(整数型・文字型のサイズは自身の処理系に依存します。)
バイト数 | C++ | C# |
---|---|---|
1 | char | sbyte |
2 | wchar_t | char |
2 | short | short |
4 | int | int |
4 | long | --- |
8 | __int64(Microsoft固有) | long |
※コメントでご指摘頂いた点
C++にlong
型は存在しません。整数型はint
であり、short
/long
/long long
は整数型のサイズを指定する修飾子です(unsigned
/signed
は符号の有無を指定する修飾子)。修飾子が使用されている場合にのみint
を省略することができます。
オブジェクト型の引数の受け渡し方
DLLでの引数の受け取り方
ポインタ型の引数を受け取り、Marshal.PtrToStringAuto
でstring型
に変換します。
[DllExport]
public static bool hoGE(IntPtr pTmp)
{
var sTmp = Marshal.PtrToStringAuto(pTmp);
・・・
}
呼び出し側の引数の渡し方
今回は以下のようにヘッダーを作成しました。
クラス内に関数ポインタ型の変数を宣言し、コンストラクタで変数に関数のポインタを格納します。
auto dll = ::LoadLibrary("EM.dll");
typedef bool (*HOGE)(const wchar_t*);
class EM
{
public:
EM();
~EM();
HOGE hoge;
};
EM::EM()
{
hoge = reinterpret_cast<HOGE>(::GetProcAddress(dll, "hoGE"));
}
EM::~EM()
{
if (dll)
::FreeLibrary(dll);
}
hogeの引数の型がconst wchar_t*
なので、CString
型をCStringW
に変換し、GetString()
を行うことでポインタを渡しています。
EM EMD;
void Check(CString strFunc)
{
CStringW Tmp = strFunc;
EMD.hoge(Tmp.GetString());
・・・
}
参考サイト
参考にさせていただいたサイトです。