4

pinvoke を使用して、別の構造内の構造の配列を C から C# にマーシャリングしようとしています。私の知る限り、できません。
代わりに、C 構造体で配列への ptr と malloc を宣言します。問題: 1) C# 側で同等のものを宣言するにはどうすればよいですか? 2) C# 側で同等のものを割り当てて使用するにはどうすればよいですか?

//The C code
typedef struct {
       int a;
       int b; } A;
typedef struct {
      int c;
      // A myStruct[100];    // can't do this, so:
      A *myStruct; } B;

//The c# code:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class A{
    int a;
    int b;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class B{
      int c;
      // can't declare array of [100] A structures...
     ?
 }

[編集]: どういうわけか、c# 側のオブジェクトの固定配列について他の場所で読んだことを誤解しました。そして、Cで配列サイズを修正できますので、コンパイルはOKですが、次を使用すると「オブジェクト参照がオブジェクトのインスタンスに設定されていません」と表示されます。

data.B[3].a = 4567; したがって、このエラーが何であるかについて他の場所で読んで、次のメソッドを追加しました。

public void initA()
        {
          for (int i = 0; i < 100; i++) { B[i] = new A(); }
        }

再度、コンパイルはOKですが、同じエラー メッセージが表示されます。

4

1 に答える 1

5

このような「複雑な」構造を C と C# の間でマーシャリングするには、いくつかのオプションがあります。

この場合、固定配列を C 側の構造に埋め込むことを強くお勧めします。これにより、C# 側が大幅に簡素化されます。この属性を使用してMarshalAs、実行時に配列に割り当てる必要がある領域を C# に伝えることができます。

// In C:
typedef struct
{
 int a;
 int b;
} A;

typedef struct
{
 int c;
 A data[100];
} B;

// In C#:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct A 
{
  int a;
  int b;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct B
{
  int c;
  [MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
  A[] data = new data[100];
}

配列の固定サイズがわからない、または指定できない場合は、行ったことを実行して、C でポインターとして宣言する必要があります。この場合、C# にメモリ量を伝えることはできません。配列は実行時に使用されるため、すべてのマーシャリングを手作業で行うことにかなり苦労しています。この質問には、それがどのように機能するかの概要がありますが、基本的な考え方は次のとおりです。

  1. 配列要素の数を含む構造体にフィールドを追加する必要があります (これにより、作業がはるかに簡単になります)。
  2. C# でフィールドを次のように宣言しIntPtr data;ます。属性はありません。
  3. Marshal.SizeOf(typeof(A))アンマネージ メモリ内の構造体のサイズを取得するために使用します。
  4. Marshal.PtrToStructure単一のアンマネージ構造を C# に変換するために使用します
  5. IntPtr.Add(ptr, sizeofA)配列内の次の構造体に移動するために使用します
  6. なくなるまでループします。
于 2012-08-15T13:32:38.700 に答える