今回2度目の質問をさせていただきます。
開発環境はVisual Studio 2013です。
実現したいこと
C#で書かれた実行プログラム(A.exe)からC++で書かれたライブラリ(B.dll)内の関数(Func_C)を呼び出す際、引数として渡す、
構造体の配列(struct_D)をA.exe側で受け取りたい。
発生している問題
A.exeからFunc_Cをコールした後、struct_Dがnullである。
(Func_Cの実行結果が格納されない)
試したこと
・下記コードのようなプログラムを実装してみました。その結果、以下のことは可能でした。
・A.exeからB.dll側に値(int型、int型・char型を含む構造体)を引数として渡すことはできる。
(下記コード内の関数1の入力引数はB.dll側に問題なく渡せる)
・B.dll側からA.exe側に値(int型)を引数として渡すこともできる。
(下記コード内の関数2の出力引数はA.exeに問題なく返せる)
以上の結果より、問題は呼び出し元にあると考え、試行錯誤していますが、うまく実装できずにいます。
下記コード内で誤り等ありましたらご教示頂けませんでしょうか。
お手数ですが宜しくお願い致します。
<A.exe(呼び出し元)>
class Program { // C++受渡し用構造体 [StructLayout(LayoutKind.Sequential)] internal struct struct_D { // 変数宣言(マーシャリング) [MarshalAs(UnmanagedType.I4)] internal int val1; // 値1 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] internal string val2; // 値2(値が省略("")の可能性あり) [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 60)] internal string val3; // 値3 // カプセル化 public int Val1 { get { return val1; } set { val1 = value; } } public string Val2 { get { return val2; } set { val2 = value; } } public string Val3 { get { return val3; } set { val3 = value; } } } // < C++のDLLファイルより関数を取得 > // 関数1(配列サイズ取得関数)←こちらは問題なく動作する [DllImport("B.dll")] static extern int GetTotal( IntPtr ptrTotal // (出力引数)←出力引数もint型変数のみであれば問題なく受け取れる ); // 関数2(構造体配列の取得関数) [DllImport("B.dll")] static extern int Func_C( IntPtr[] dataOut, // (出力引数)ポインタの配列(これが受け取れない) int num, // (入力引数)←入力引数はB.dllに問題なく渡せる struct_D dataIn // (入力引数)←構造体も問題なく渡せる ); static internal int Func_E() { // 出力構造体の配列サイズを取得(これは問題なく動作する) IntPtr ptrTotal = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int))); // レコード数ポインタ(メモリ確保) Marshal.StructureToPtr(Total, ptrTotal, false); // レコード数とポインタを結び付け GetTotal(ptrTortal); // DLLの実行(レコード数取得) Total = (int)Marshal.PtrToStructure(ptrTotal, typeof(int)); // ポインタから値(int型)を取得 Marshal.FreeHGlobal(ptrTotal); // メモリ解放 // 出力構造体分のバッファ確保(これが問題) int ii; struct_D[] dataOut = new struct_D[Total]; // 出力構造体の宣言 IntPtr[] ptrdataOut = new IntPtr[Total]; // 出力構造体のポインタの宣言 for (ii = 0; ii < Total; ii++) // 出力構造体のサイズ分のメモリを確保 { ptrdataOut [ii] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(struct_D))); Marshal.StructureToPtr(dataOut[ii], ptrdataOut[ii], false); } // DLLの関数実行 Func_C(ptrdataOut, num, dataIn); // ポインタから値(構造体)を取得(受け取れない…) for (ii = 0; ii < Total; ii++) { dataOut[ii] = (struct_D)Marshal.PtrToStructure(ptrdataOut[ii], typeof(struct_D)); Marshal.FreeHGlobal(ptrdataOut[ii]); } } }
<B.dll(呼び出し先)>
// C#受渡し用構造体 struct gyddwsproduct { long val1; // 値1 char val2[16]; // 値2(値が省略("")の可能性あり) char val3[60]; // 値3 } // 関数1(配列サイズ取得関数)←こちらは問題なく動作する DLLEXPORT int __stdcall GetTotal(int* Total) { … } // 関数2(構造体配列の取得関数) DLLEXPORT int __stdcall Func_C(struct_D* dataOut, int num, struct_D dataIn) { … // 入力引数(num, dataInは問題なく取得できている) }
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/06/14 23:26
2019/06/16 11:27
2019/07/08 09:54