はじめに
当記事は @TackKaiwareさまの、
「C#からC/C++の関数をコールする方法 まとめ①」を基に作成されています。
C#からC++の関数コールをして、構造体を構造体ポインタとして渡してみます。
ソースコード
C++ dll ソースコード
mylib.h
#include <Windows.h>
typedefstruct_MY_STRUCT{boolmyFlag;char*name;void*output;};extern"C"__declspec(dllexport)intTest(PVOIDmystruct);
mylib.cpp
#include <iostream>
#include "mylib.h"
intTest(PVOIDmystruct){_MY_STRUCT*ms=(_MY_STRUCT*)mystruct;std::cout<<"CPPの関数が呼び出されました。"<<std::endl;if(ms->myFlag){std::cout<<"Flag on"<<std::endl;}else{std::cout<<"Flag off"<<std::endl;}std::cout<<"name: "<<ms->name<<std::endl;std::cout<<"output: "<<ms->output<<std::endl;return634;}
C# WinForm
MyForm.cs
publicstruct_MY_STRUCT{publicboolmyFlag;publicstringname;publicfloatoutput;}[DllImport("mylib.dll")]publicunsafestaticexternintTest(IntPtrpStructure);privateunsafevoidButton1_Click(objectsender,EventArgse){_MY_STRUCTmyStruct=new_MY_STRUCT();myStruct.myFlag=true;myStruct.name="SETOKOUJI";myStruct.output=999.9f;IntPtrpStructure=Marshal.AllocCoTaskMem(Marshal.SizeOf(myStruct));Marshal.StructureToPtr(myStruct,pStructure,false);intx=Test(pStructure);WriteLog(x.ToString());Marshal.FreeCoTaskMem(pStructure);}
実行結果
構造体のマーシャリング
構造体を「構造体ポインタ」として渡す為、該当構造体をマーシャリングする必要があります。
アンマネージドメモリを確保し、Marshal.StructureToPtr
を使用して構造体ポインタへと変換します。
IntPtrpStructure=Marshal.AllocCoTaskMem(Marshal.SizeOf(myStruct));Marshal.StructureToPtr(myStruct,pStructure,false);
今回は各チェックは省いています。
if(pStructure==IntPtr.Zero||pStructure==null){return;}
最後にリソースを開放します。
Marshal.FreeCoTaskMem(pStructure);
C++側: Voidポインタから構造体への変換
PVOID mystruct
はVoidポインタ(void*
)です。
関数コールの際に構造体ポインタを受け取ります。
intTest(PVOIDmystruct){_MY_STRUCT*ms=(_MY_STRUCT*)mystruct;}
構造体ポインタから構造体へのキャストは、下記でも同様です。
_MY_STRUCT*ms=static_cast<_MY_STRUCT*>(mystruct);
おわり
今回は、C#からC/C++の関数をコールして構造体を渡してみました。
同様にして、dll側から返り値として構造体を渡すこともできます。