2012-05-10 15 views
2

これを行うには複数の方法があるようですが、試した例は私のために働いていません。PInvokeスタイルのメンバーを持つ構造体を渡すポインタの動的配列

安全でないポインタを使用すると、ポインタを必要とするより複雑な構造に移行する方法があります。私はSubStructは、(署名がInteropされていないマーシャリングすることができないと言うエラーが出る

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); 
} 
} 

:(申し訳ありませんが、私は再びソースを見つけることができませんでした)

私の最新の試みは、次のようになります互換性あり)。

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

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

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

EDIT: いくつかの注意事項:

  1. 配列は、実際の構造体は、もう少し複雑なダイナミック
  2. をすることによってする必要があります(このようなネストされた構造の4層があります)ので、私は追加することだと思います彼らは質問を損なうが、完全を期すために、ここで私はC++でこれらを宣言するだろうかあるでしょう:

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

(余分な間接は必要ありませんが、私はIntPtrsとしてSubStructポインタの配列を宣言できるようにするには便利かもしれません考え出し)

+0

2つの構造体のC++宣言を表示できますか?個人的には、私は「不安全」が行く方法であることを非常に疑う。 –

+0

余計な間接指示があなたを傷つけるでしょう。それがなければ簡単になるでしょう。 –

答えて

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(pnt); 
} 

は、私がその必要を疑う、すべての危険なものを取り除くようにしてください!

+0

私は、SizeConstに任意に高い数値を使用するとパフォーマンスが非常に悪くなると想定しています。ダイナミックにするためのアイデア? – 00500005

+0

動的に行うには十分なはずです。 –

+0

これはうまくいきませんが、SizeConstはおそらくMarshal.SizeOf()のためのものです。自分でサイズを計算すると、それを動的に行うことができるはずです。最悪の場合、StructureToPtrはうまく動作せず、各SubStructureを自分自身でコピーしなければなりません。 – DavWEB

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); 
    } 
} 
+0

上記と 固定(SubStruct * sp1 =&s [0]) 固定(SubStruct * sp2 =&s [1]) 固定(SubStruct ** spp =新規SubStruct * [] {sp1、sp2}) メモリアクセス違反。 DLLが実行され、データは正しく渡されたように見えます(少なくとも2番目のバージョンでは)。 – 00500005

関連する問題