4

これを行うには複数の方法があるように見えますが、私が試した例はうまくいきませんでした。

私はどこかで、安全でないポインターを使用することが、ポインターを必要とするより複雑な構造を求める方法になるだろうと読みました。(申し訳ありませんが、ソースを再度見つけることができませんでした)

私の最近の試みは次のようになります。

unsafe public struct ComplexStruct {
    public Int32 NumSubStruct;
    public SubStruct*[] arr;
}

unsafe public static extern UInt32 DLL_Call(ref ComplexStruct p);

function {
unsafe {
    ComplexStruct p = new ComplexStruct();
    p.NumSubStruct = 2;
    p.arr= new SubStruct*[p.NumSubStruct];
    SubStruct p1 = new SubStruct();
    SubStruct p2 = new SubStruct();
    p.arr[0] = &p1;
    p.arr[1] = &p2;


    testLogHandlerHandle = DLL_Call(ref p);
}
}

SubStructをマーシャリングできないというエラーが表示されます(署名は相互運用互換ではありません)。

マーシャリングせずにオブジェクトを渡すことは可能ですか?(DLLはC#アプリケーションと同じプロセススペースにロードする必要があります)。

そうでない場合、オブジェクトのコピーを渡す最も簡単な方法は何でしょうか?

注:DLLの変更は問題ではありません。私はC++/ CLIなどの他のいくつかのソリューションを漠然と認識していますが、そのような方法で渡す必要のある構造体タイプは比較的少数しかありません。

編集: いくつかのメモ:

  1. アレイは動的である必要があります
  2. 実際の構造体はもう少し複雑なので(このようなネストされた構造体は4層あります)、それらを追加すると質問が損なわれると思いますが、完全を期すために、C++でこれらを宣言する方法を次に示します。

    struct ComplexStruct {
    
         unsigned int NumSubStruct;
    
         SubStruct** arr;
    
    };
    
    struct SubStruct {
    
         unsigned int NumSubStruct;
    
         //some more datamembers here as well
    
         SubSubStruct** arr;
    
    };
    

(余分な間接参照は必要ありませんが、SubStructポインターの配列をIntPtrsとして宣言できると便利かもしれないと思いました)

4

2 に答える 2

1

このように多分?

unsafe public struct ComplexStruct 
{ 
  public Int32 NumSubStruct; 
  public SubStruct** arr; 
}

unsafe static void Main(string[] args)
{
  ComplexStruct p = new ComplexStruct();
  p.NumSubStruct = 2;
  SubStruct[] s = new SubStruct[p.NumSubStruct];
  // no need to new here, valuetype array
  s[0].value = 1;
  s[1].value = 2;
  fixed (SubStruct* sp = s)
  fixed (SubStruct** spp = new SubStruct*[] { sp })
  {
    p.arr = spp;
    testLogHandlerHandle = DLL_Call(ref p);
  }
}
于 2012-05-10T20:08:28.247 に答える
0

thisthisのようなものを使用する必要があります。

[StructLayout(LayoutKind.Sequential)]
public struct ComplexStruct
{
    public Int32 NumSubStruct;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_NO_SUB_STRUCTS)]
    public SubStruct[] arr;
}

public static extern UInt32 DLL_Call(IntPtr p);

次に、次のようなものでマーシャリングします。

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ComplexStruct)));

try
{
    // Copy the struct to unmanaged memory.
    Marshal.StructureToPtr(p, ptr, false);

    testLogHandlerHandle = DLL_Call(ptr);
}
finally
{
    // Free the unmanaged memory.
    Marshal.FreeHGlobal(ptr);
}

すべての安全でないものを取り除くようにしてください。私はそれが必要だとは思いません!

于 2012-05-10T19:54:45.447 に答える