我正在使用自己的编码(marshal)拆收器,该编码(marshal)拆收器实现 ICustomMarshaler 以与 native (非托管)dll C 函数配合使用。
在函数 MarshalNativeToManaged 中,我确实看到来自 dll 端的正确结果。问题在于 MarshalNativeToManaged 返回的对象未“使用”。带有 (In, Out) 参数的调用函数中的对象不会更改。
(看起来与之前讨论的问题完全相同“C#:具有自定义编码器的对象在 PInvoke 调用后不包含数据”) C#: Object with custom marshaller not containing data after PInvoke call
简单类:
[StructLayout(LayoutKind.Sequential)]
class CMA {
public int a;
char b;
public char get_b() { return b; }
}
函数的签名如下所示:
[DllImport("first.dll", EntryPoint = "hack")]
public static extern int hack([In, Out, MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef=typeof(ZMarshal))] CMA cma);
在主要部分我这样调用它:
int retcode = hack(cma);
在 MarshalNativeToManaged 中,我确实看到了 dll 函数调用的正确结果。
public object MarshalNativeToManaged(IntPtr pNativeData)
{
// everything is fine with pNativeData;
// but let us even say I ignore it
// and return the object in the following way:
CMA cma = new CMA();
cma.a = 999;
return cma; // this will be lost. I mean cma object in the main will not be changed
}
我在这里做错了什么? 只是一个快速说明:我确实想知道如何使用 CustomMarshaler 来处理它,而不是“其他方式”:)
最佳答案
好吧,看起来我知道现在发生了什么。
诀窍在于,在处理 Object 时,我们实际上是在处理指针(无论 C# 如何努力隐藏这一事实),并且一步一步: 1) 破解(CMA* pCMA); 2) MarshalManagedToNative(void* pCMA)//C# 将我们传递给 hack 的指针传递给这里 3) void* MarshalNativeToManaged(void *_some_PTR_to_memory_visible_to_driven_and_undriven_area) 这里的问题是 .NET 对该函数返回的 Void* ptr 做了什么?如果不使用 ref,则无法更改 hack(cma) 中的对象。这个指针根本没有在任何地方使用。该函数可能无效。
public class ZMarshal : System.Runtime.InteropServices.ICustomMarshaler
{
static ZMarshal static_instance;
object oo;
public IntPtr MarshalManagedToNative(object o)
{
if (!(o is CMA))
throw new System.Runtime.InteropServices.MarshalDirectiveException("Blabala");
oo = o;
稍后在 MarshalNativeToManaged 中
public object MarshalNativeToManaged(IntPtr pNativeData)
{
// some code that deals with the pNativeData really
// but for our example only let us say we simply ignore what we just got
// from the unmanaged world and simply change our object
((CMA)oo).a = 999;
return oo; // this will not be lost now :)
如果我们像这个 hack(ref CMA) 一样使用 ref ;//顺便说一句,感谢之前的回答 在本例中,它是 hack(CMA**pp) 并且 .NET 确实使用我们从 MarshalNativeToManaged *pp = oo; 返回的指针
底线是我们要么必须保留指针并更改它指向的内存值,要么(使用 ref)将指针传递给指针(是的,确实很好**)并更改指针本身的值.
关于c# - ICustomMarshaler::MarshalNativeToManaged,从 native dll “looses” 它返回的对象接收正确的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10745225/