2012-02-24 1 views
1

私は次のように定義される「C」のstruct持っている:私は、この関数にPInvokeのにstructに整数の配列が含まれている場合、PInvokeマーシャリング時のコピーを避けるにはどうすればよいですか?

void FillTest(tUI8 Mode, TestStruct *s); 

typedef unsigned char tUI8; 

typedef struct 
{ 
    tUI8 Mode; 
    tUI8 Data[16]; 
} TestStruct; 

そして、この構造体へのポインタを受け取り、データを埋める機能をこれは動作しますが、私はのPInvokeマーシャラー中に通話中に構造体をコピーしているし、それを固定するのではなく返すことが疑われる

[StructLayout(LayoutKind.Sequential)] 
struct TestStruct 
{ 
    public byte Mode; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
    public byte[] Data; 
} 

static class NativeTest 
{ 
    [DllImport("Native.dll")] 
    public static extern void FillTest(byte mode, ref TestStruct s); 
} 

:としてC#コードを書きました。構造体を初期化しなくてもうまく動作するからです。

TestStruct s; 
//here s.Data == null! 
NativeTest.FillTest(10, ref s); //<<< I expected an error here 
//here s.Data points to a valid byte[] of length 16 
Console.WriteLine(BitConverter.ToString(s.Data)); 

私の質問は、マーシャリング時にデータをコピー避けた、私は構造体やクラスのいずれかを使用して、のPInvokeシグネチャを定義する方法ですか?

答えて

2

私はあなたの構造体にデータをインライン化しますfixed size bufferを、欲しい疑う:

[StructLayout(LayoutKind.Sequential)] 
unsafe struct TestStruct 
{ 
    public byte Mode; 
    public fixed byte Data[16]; 
} 

あなたは今、あなたのアンマネージコードに直接参照することによってそれを渡すことができるはずです。 (明示的に危険なコードを許可することも必要があります。)

私はいかなる場合は、その後、マーシャリングのために使用する必要がありますが、それは試してみる価値の属性かわからない...

+0

注意として、マーシャリングすることで

、およびプロジェクトのプロパティで、安全でないコードを許可するチェック。 – linquize

+0

うん。私はそれを試して、それは動作しますが、私は(安全ではないとマークして)私が悪い人であることを何度も宣言しなければなりませんでした。私はまた、呼び出し中にmarshallerが自動的に構造体を固定するかどうか、または明示的にそれを行う必要があるかどうかについてはわかりません。 – Hemant

+0

@Hemantコピーを避けたい場合は、安全でないものを使用する必要があります。安全でないことを避けたい場合は、マーシャラーのコピーを許可する必要があります。データをコピーするのはどうですか? –

0

この安全でないコードを使用せずに行うことができます。危険な構造体をマークし、それが安全ではないことをByValArray

[StructLayout(LayoutKind.Sequential)] 
struct TestStruct 
{ 
    public byte Mode; 

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
    public byte[] Data; 
} 
関連する問題