简体   繁体   English

PInvoke样式传递带有成员动态指针数组的结构

[英]PInvoke style passing struct with member dynamic array of pointers

There appears to be multiple ways to do this, but the examples I've tried haven't worked for me. 似乎有多种方法可以做到这一点,但我尝试的例子对我没用。

I read somewhere that using unsafe pointers would be the way to go for more complex structures that require pointers. 我在某处读到,使用不安全的指针将成为需要指针的更复杂结构的方法。 (sorry but I haven't been able to find the source again) (抱歉,但我再也找不到来源了)

My latest attempt looks something like this: 我的最新尝试看起来像这样:

unsafe public struct ComplexStruct {
    public Int32 NumSubStruct;
    public SubStruct*[] arr;
}

unsafe public static extern UInt32 DLL_Call(ref ComplexStruct p);

function {
unsafe {
    ComplexStruct p = new ComplexStruct();
    p.NumSubStruct = 2;
    p.arr= new SubStruct*[p.NumSubStruct];
    SubStruct p1 = new SubStruct();
    SubStruct p2 = new SubStruct();
    p.arr[0] = &p1;
    p.arr[1] = &p2;


    testLogHandlerHandle = DLL_Call(ref p);
}
}

I get an error which says that SubStruct cannot be marshaled (Signature is not interop compatible). 我收到一个错误,说SubStruct无法编组(签名不兼容)。

Is it possible to pass the object without marshaling? 是否可以在没有编组的情况下传递对象? (the DLL should be loaded in the same process space as the C# application). (DLL应该在与C#应用程序相同的进程空间中加载)。

If not, what would be the simplest way to pass a copy of the object? 如果没有,传递对象副本的最简单方法是什么?

Note: changing the DLL is a non-issue. 注意:更改DLL不是问题。 I am vaguely aware of some other solutions, such as C++/CLI, but I only have a relatively small number of structure types that need to be passed in such a way. 我隐约知道其他一些解决方案,例如C ++ / CLI,但我只有相对少量的结构类型需要以这种方式传递。

EDIT: A few notes: 编辑:一些注意事项:

  1. The array needs to by dynamic 数组需要动态
  2. The actual structs a bit more complicated (there's 4 layers of nested structures like this) so I think adding them would detract from the question, but for completeness, here is how I would declare these in C++: 实际的结构有点复杂(有4层这样的嵌套结构),所以我认为添加它们会减损问题,但为了完整性,我将在C ++中声明这些:

     struct ComplexStruct { unsigned int NumSubStruct; SubStruct** arr; }; struct SubStruct { unsigned int NumSubStruct; //some more datamembers here as well SubSubStruct** arr; }; 

(the extra indirection isn't necessary, but I figured it might be useful to be able to declare the array of SubStruct pointers as IntPtrs) (额外的间接是没有必要的,但我认为能够将SubStruct指针数组声明为IntPtrs可能很有用)

Like this maybe? 也许这样吗?

unsafe public struct ComplexStruct 
{ 
  public Int32 NumSubStruct; 
  public SubStruct** arr; 
}

unsafe static void Main(string[] args)
{
  ComplexStruct p = new ComplexStruct();
  p.NumSubStruct = 2;
  SubStruct[] s = new SubStruct[p.NumSubStruct];
  // no need to new here, valuetype array
  s[0].value = 1;
  s[1].value = 2;
  fixed (SubStruct* sp = s)
  fixed (SubStruct** spp = new SubStruct*[] { sp })
  {
    p.arr = spp;
    testLogHandlerHandle = DLL_Call(ref p);
  }
}

You should use something like this and this . 你应该使用类似这样这个

[StructLayout(LayoutKind.Sequential)]
public struct ComplexStruct
{
    public Int32 NumSubStruct;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_NO_SUB_STRUCTS)]
    public SubStruct[] arr;
}

public static extern UInt32 DLL_Call(IntPtr p);

Then marshal it with something like this: 然后用这样的东西编组它:

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ComplexStruct)));

try
{
    // Copy the struct to unmanaged memory.
    Marshal.StructureToPtr(p, ptr, false);

    testLogHandlerHandle = DLL_Call(ptr);
}
finally
{
    // Free the unmanaged memory.
    Marshal.FreeHGlobal(ptr);
}

Try to get rid of all the unsafe stuff, I doubt its necessary! 试着摆脱所有不安全的东西,我怀疑它是必要的!

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

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