2

私は構造を持っています -->

   public struct readers
   {
       [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)]
       public IntPtr[] tag_list;
   };

マーシャリングは、「IntPtr[] tag_list」と構造体 TAG_IN_PARAM の間で行う必要があります

   [StructLayout(LayoutKind.Sequential)]
   internal struct TAG_IN_PARAM
   {
       public int vis_cnt;
       public bool valid;
   }

=> TAG_IN_PARAM[] tag_list = new TAG_IN_PARAM[1000]; のような配列もあります。

C# から C++ DLL に構造体「リーダー」を渡したい。ただし、マーシャリングを行っていますが、DLL側でガベージ値が発生しています。

// メモリを割り当てます Marshal.StructureToPtr(tag_list[j], Reader.tag_list[j], false);

または、私にできる他の方法があれば、伝えてください。どんな助けでも大歓迎です。前もって感謝します。

4

1 に答える 1

0

コメントによると、一致させようとしている C++ の型は次のとおりです。

class Readers 
{
public:
    TAG_IN_PARAM* tag_list;
};

それは配列へのポインタです。

しかし、C# コードはインライン配列を宣言しています。C# コードは次のようになります。

class Readers 
{
public:
    TAG_IN_PARAM tag_list[1000];
};

明らかに、それはあなたが行きたい方法ではありません。

一致させるには、C# コードを変更する必要があります。残念ながら、配列が構造体内にある場合、マーシャラーは配列を最初の要素へのポインターとしてマーシャリングしないようです。配列は構造体の唯一のものであるため、単に配列をパラメーターとして渡す必要があります。

または、構造体で配列を渡す必要がある場合は、手動でマーシャリングする必要があると思います。このような。

public struct readers
{
    public IntPtr tag_list;
};

そして、配列を固定するだけです。

TAG_IN_PARAM[] tag_list = ...;
GCHandle pinnedArray = GCHandle.Alloc(tag_list, GCHandleType.Pinned);
readers r;
r.tag_list = pinnedArray.AddrOfPinnedObject();
// call function passing r
pinnedArray.Free();

残念ながら、C#boolは blittable ではないため、うまくいきません。したがって、そのフィールドに別のタイプを使用することで解決できます。たとえば、byteまたはintC++側にあるものに応じて。

さらに別のオプションがMarshal.StructureToPtr各フィールドにあります。これは次のように実行されます。

TAG_IN_PARAM[] tag_list = ...;
int structSize = Marshal.SizeOf(typeof(TAG_IN_PARAM));
r.tag_list = Marshal.AllocHGlobal(tag_list.Length*structSize);
IntPtr ptr = r.tag_list;
for (int i = 0; i < tag_list.Length; i++)
{
    Marshal.StructureToPtr(tag_list[i], ptr, false);
    ptr += structSize;
    // or on older versions of .net without arithmetic support on IntPtr
    // ptr = (IntPtr) (long)ptr + structSize;
}
// call function passing r
Marshal.FreeHGlobal(r.tag_list);
于 2013-09-13T08:53:11.333 に答える