2009-08-24 23 views
5

文字列の配列へのポインターをマーシャリングするときに問題が発生します。これは、このような無害に見える:文字列の配列へのポインターのマージ

typedef struct 
{ 
    char* listOfStrings[100]; 
} UnmanagedStruct; 

これは、実際にこのような別の構造の中に埋め込まれている:

typedef struct 
{ 
    UnmanagedStruct umgdStruct; 
} Outerstruct; 

アンマネージコードをマネージコードにコールバックし、割り当てられたメモリとのIntPtrとしてOuterstruct返し、記入値。

管理の世界:

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeConst=100)] 
    public string[] listOfStrings; 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct Outerstruct 
{ 
    public UnmanagedStruct ums; 
} 

public void CallbackFromUnmanagedLayer(IntPtr outerStruct) 
{ 
    Outerstruct os = Marshal.PtrToStructure(outerStruct, typeof(Outerstruct)); 
    // The above line FAILS! it throws an exception complaining it cannot marshal listOfStrings field in the inner struct and that its managed representation is incorrect! 
} 

listOfStringsを単にIntPtrに変更すると、Marshal.PtrToStructureは機能しますが、今はlistOfStringsをリッピングして文字列を1つずつ抽出することができません。

答えて

1

を文字列に変換し、ラッパープロパティを追加し、[OK] ..私はそれが動作するように持っているように見えます。それはのIntPtr []は

これが動作しているようですとしてマーシャリングする必要があります。

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=100)] 
    public IntPtr[] listOfStrings; 
} 

for (int i = 0; i < 100; ++i) 
{ 
    if (listOfstrings[i] != IntPtr.Zero) 
     Console.WriteLine(Marshal.PtrToStringAnsi(listOfStrings[i])); 
}  
+0

ByValArray ==インプレイス配列、LPArray ==配列へのポインタです。 SizeConstはまだLPArrayで動作するはずですが、マーシャリング時のエラーはちょっと奇妙でした。 –

+0

ああ、パブリックstring [] listOfStrings、それは私が信じている違いを作るByValArrayを持っている場合は、それも動作するはずです。 –

4

非常に基本的な文字列以外のものをマーシャリングすることは、複雑であり、見つけにくいサイドケースでいっぱいです。通常、構造体定義の安全な/単純なルートを使用し、いくつかのラッパープロパティを整理して整理するのが最善です。

この場合、私はのIntPtrの配列に移動して

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeConst=100)] 
    public IntPtr[] listOfStrings; 

    public IEnumerable<string> Strings { get { 
     return listOfStrings.Select(x =>Marshal.PtrToStringAnsi(x)); 
    } 
} 
+0

ジャレッド 感謝を検証するために!あなたのことを見る前に自分の質問に答えを投稿しました。 1つの質問 - 投稿でコードをどのようにフォーマットするのですか?彼らはすべて見えなくなってしまい、誰かがいつも編集し修正しなければなりません。 – Dilip

+0

@Dilipでコードスニペットを選択し、Ctrl + Kキーを押します。それは、すべての4つのspcaes – JaredPar

+0

@ Jaredをインデントすることによってフォーマットを修正します:ちょっとしたフォローアップ。 UnmanagedType.LPArrayを使用するとコードは爆発し続けます。 UnmanagedType.ByValArrayのみが動作します。私は今KeeperOfTheSoulが彼/彼女のコメントで示唆していたものを理解する。 – Dilip

関連する問題