Returning pointers from unmanaged to managed code

…衆ロ難τιáo~ 提交于 2019-12-19 02:31:20

问题


I've an unmanaged dll that exports the folowing function:

SomeData* test();

Let's assume SomeData as:

typedef struct _Data Data;  
struct _Data{  
    int a;  
    int b;  
}

Now i want to call this function from C# code. I start to define the C# Struture needed to custom marshaling like this:

[StructLayout(LayoutKind.Sequential)]  
public class SomeData  
{  
    public Int32 a;  
    public Int32 b;  
}  

And now, i declare the managed function:

[DllImport("DynamicLibrary.dll", CharSet=CharSet.Auto)]  
[return: MarshalAs(UnmanagedType.LPStruct)]  
public static extern SomeData test();  

And in the main function i have:

IntPtr ptr = test();  

Doing this, i get the MarchalDirectiveException: "Cannot marshal 'return value': Invalid managed/unmanaged type combination (Int/UInt must be paired with SysInt or SysUInt)."

I did not allocate the memory for SomeData in C# since i expect this memory is allocated in the C function and them i would use the Marshal.Copy to pass it to the managed memory.

Any ideas? Thanks

------------------------ EDITED AFTER JaredPar ANSWER --------------------

In fact, i committed a mistake when coping the code to my question. The real managed signature i was using was:

[DllImport("DynamicLibrary.dll", CharSet=CharSet.Auto)]
[return: MarshalAs(UnmanagedType.LPStruct)]
public static extern IntPtr test();

The JaredPar's answer is still relevant. To get the right behaviour, i have 2 choices:

1) Use the 'public static extern IntPtr test();' (without MarshalAs attribute) signature and then access the returned pointer like JaredPar suggested.

2) Use the 'public static extern SomeData test();' (with MarshalAs attribute) and then simply use SomeData sd = test();


回答1:


When declaring the managed function you need to match pointer types with reference values or IntPtr values. In this case the LPStruct modifier won't help. The easiest solution is to convert the return value of test to be an IntPtr rather than SomeData since the native method is returning a pointer value. You can then write the following wrapper

[DllImport("DynamicLibrary.dll", CharSet=CharSet.Auto)]
public static extern IntPtr test();

public static SomeData testWrapper() {
  var ptr = test();
  try {
    return (SomeData)Marshal.PtrToStructure(ptr, typeof(SomeData));
  } finally {
    // Free the pointer here if it's allocated memory
  }
}


来源:https://stackoverflow.com/questions/2338146/returning-pointers-from-unmanaged-to-managed-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!