简体   繁体   English

使用IntPtr将结构数组从C#传递到C ++

[英]passing an array of structures from C# to C++ using IntPtr

I have a structure --> 我有一个结构->

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

Marshalling has to be done in between "IntPtr[] tag_list" & structure TAG_IN_PARAM 必须在“ IntPtr [] tag_list”和结构TAG_IN_PARAM之间进行编组

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

Also its an array as => TAG_IN_PARAM[] tag_list = new TAG_IN_PARAM[1000]; 同样,它的数组为=> TAG_IN_PARAM [] tag_list =新的TAG_IN_PARAM [1000];

I want to pass structure "readers" from C# to C++ DLL. 我想将结构“阅读器”从C#传递到C ++ DLL。 However, i have been doing marshalling but garbage value is coming on DLL side. 但是,我一直在进行编组,但是DLL端的垃圾值不断增加。

// allocating memory Marshal.StructureToPtr(tag_list[j], Reader.tag_list[j], false); //分配内存Marshal.StructureToPtr(tag_list [j],Reader.tag_list [j],false);

OR IF ANY OTHER WAY I CAN DO IT, PLEASE CONVEY. 或者,如果我可以通过其他任何方式,请方便。 Any help would be appreciated. 任何帮助,将不胜感激。 Thanks in Advance. 提前致谢。

The C++ type that you are trying to match is, according to your comment: 根据您的评论,您要匹配的C ++类型是:

class Readers 
{
public:
    TAG_IN_PARAM* tag_list;
};

That's a pointer to an array. 那是指向数组的指针。

But your C# code declares an inline array. 但是您的C#代码声明了一个内联数组。 Your C# code would match this: 您的C#代码将与此匹配:

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

Obviously, that's not the way you want to go. 显然,这不是您想要的方式。

You'll need to change your C# code to make it match. 您需要更改C#代码以使其匹配。 Unfortunately it seems that the marshaller will not marshal an array as a pointer to the first element, when the array is inside a struct. 不幸的是,当数组位于结构内部时,编组器似乎不会将数组作为第一个元素的指针进行封送。 Since the array is the only thing in the struct you should simply pass the array as a parameter. 由于数组是结构中的唯一内容,因此您只需将数组作为参数传递即可。

Alternatively, if you absolutely need to pass the array in a struct then I think you need to marshal by hand. 另外,如果您绝对需要在结构中传递数组,那么我认为您需要手动编组。 Like this. 像这样。

public struct readers
{
    public IntPtr tag_list;
};

And then you can simply pin your array. 然后,您可以简单地固定阵列。

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();

Unfortunately that does not quite work because C# bool is not blittable. 不幸的是,由于C# bool不可设置,因此无法正常工作。 So you could resolve that by using a different type for that field. 因此,您可以通过对该字段使用其他类型来解决此问题。 For example byte or int depending on what's on the C++ side. 例如, byteint取决于C ++方面。

Yet another option is Marshal.StructureToPtr on each field. 每个字段上的另一个选择是Marshal.StructureToPtr That would run like this: 这样运行:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM