返回从非托管指针托管代码 [英] Returning pointers from unmanaged to managed code

查看:202
本文介绍了返回从非托管指针托管代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非托管的DLL导出如下因素的功能:

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

SomeData* test();

让我们假设SomeData为:

Let's assume SomeData as:

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

现在我想打电话给从C#代码此功能。我开始定义C#Struture需要这样的自定义编组:

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

和在主函数中我有:

IntPtr ptr = test();  



这样做,我得到的MarchalDirectiveException:不能元帅返回值:无效的托管/非托管类型组合(智力/ UINT必须SysInt或SysUInt配对)。

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

我,因为我希望这记忆在C函数分配未分配的内存SomeData在C#和他们我会用Marshal.Copy将它传递给托管内存。

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.

任何想法?谢谢

------------------------编辑完成后JaredPar答案​​------ --------------

------------------------ 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.Auto)]结果
[返回:的MarshalAs(UnmanagedType.LPStruct)结果
公共静态外部的IntPtr测试();

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

JaredPar的答案仍然是相关的。为了得到正确的行为,我有2个选择:

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

1)使用公共静态外部的IntPtr测试();'(无MarshalAs特性)签名,然后访问。回到像JaredPar指针提示

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

2)使用公共静态外部SomeData测试();'(与MarshalAs特性),然后简单地使用SomeData SD =测试()

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

推荐答案

在声明需要与参考值匹配指针类型的管理功能或的IntPtr 值。在这种情况下,LPStruct修改也无济于事。最简单的解决方法是测试的返回值转换成为一个的IntPtr ,而不是 SomeData ,因为本地方法将返回一个指针值。然后,您可以编写以下包装

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
  }
}

这篇关于返回从非托管指针托管代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆