VisualStudio 2017を使用しています。
C#からC++で作成されたDLLを読み込み、実行結果として Msgに文字列を取得したいです。
下記のようにstring型を渡しているのですが、C#へ文字列が取得でず、Msgには何も入っていない状態となります。
そこでお伺いしたいのですが、char *& に渡す方法として下記のような記述は正しいのでしょうか?
正しい方法や参考ページなどございましたら教えていただきたいです。
C++
1extern "C" __declspec(dllexport) int __stdcall Initialization(int &nTotalNum, char * & szMsg);
C#
1namespace MYClass 2{ 3 class Program 4 { 5 [DllImport("Driver.dll", CallingConvention = CallingConvention.StdCall)] //Cdecl->StdCall 6 private extern static int Initialization(IntPtr nTotalChannels, string szMsg); //int &nTotalNum, char * & szMsg) 7 8 static void Main(string[] args) 9 { 10 int nResult = -1; 11 string szStr = ""; 12 13 IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int))); 14 nResult = Initialization(ptr, szStr); 15 16 int ptrValue = Marshal.ReadInt32(ptr); 17 Console.WriteLine("Initialization : nChannelNum = {0}, szMsg = {1}", ptrValue, szStr); 18 } 19 } 20}
関数プロトタイプから推測するに、DLL/C++側で文字列メモリの動的確保を行って関数呼出し元に返す(=関数呼出し側にメモリ解放責任がある)のでしょうか?このとき、メモリの動的確保方法(malloc, new, etc...)が外部仕様として明確化されていますか?もしそうでないなら、C#側からメモリ解放する術が存在せず100%メモリリークを引き起こします。
私が作成したDLLではないため、その部分に関しては作成者に確認を取らないといけないと思います。
VisualStudioの診断ツールのプロセスメモリを見ると、実行後は実行前と同じくらいの値まで下がっているため、現状では見えていないだけかもしれませんが、メモリリークはないのではないかと考えています。
C++コードで文字列を扱う場合、メモリ確保・解放の責任が関数呼出し側/元のどちらにあるかを明確化することは非常に重要です。可能であればDLL公開関数仕様の修正がベストですが、それが不可能であってもメモリ管理責任は「外部仕様」として捉える必要があります。一般に文字列バッファのメモリリーク量は小さいことが多く、ループ内で反復関数呼出しをするなどの状況下でないと問題が表面化しないだけということは良くあります。
回答2件
あなたの回答
tips
プレビュー