2016-09-20 15 views
2

外部C DLLからコールバックを受け取るC#インターフェイスを作成しようとしています。 コールバックのパラメータには、C構造体へのポインタが含まれています。これらの構造体自体には、別の構造体へのポインタがあります。C to C#ポインタ付きの構造体を持つPInvoke

コールバック署名:Cで

typedef application_event_result (*application_event_ptr)(abuffertype* read_buffer, abuffertype* write_buffer); 

バッファ構造体の定義:

typedef struct { 
    uint16 size; 
    uint8* data; 
} anotherbuffertype; 

typedef struct { 
    anotherbuffertype *buffer; 
    uint16 position; 
} abuffertype; 

Iは、コールバックのC#の署名は、パラメータのポインタ型は、 "REF" を使用すべきであることを知っています。しかし、どのように "abuffertype"構造体の中のポインタをC#で定義することができますか?

これまでのところ私はC#で2つの構造体のこの定義があります

[StructLayout(LayoutKind.Sequential)] 
    public struct anotherbuffer 
    { 
     UInt16 size; 
     IntPtr data; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct abuffer 
    { 
     anotherbuffer buffer; 
     UInt16 position; 
    } 

をしかし、それは動作しません。 C#の "abuffer"の内容は、Cコードのコールバックの前にあったものではありません。

内部構造体ポインタを手動でアンマーシャリングする必要がありますか?

答えて

2

あなたはマーシャラの助けを借りないでしょう。これは、通常、大きなメモリ管理の問題を引き起こします。しかし、データを管理するコール元のCプログラムであるため、コールバックの特定のケースで動作することができます。

自分でデータを変換する必要があります。ポインターをIntPtrと宣言し、Marshal.PtrToStructure()を使用してデータを取得します。

anotherbuffertype.dataメンバーは配列のように見えますが、Marshal.Copy()を使用してコンテンツを独自のbyte []配列にコピーします。 unsafeキーワードを気にしない場合は、バイト*として宣言されたままにして、データ[インデックス]で要素にアクセスしてコピーのコストを回避できます。非常に安全ではなく、インデックスを[0..size]に制限するのはかなり簡単です。

関連する問題