English 中文(简体)
ICustomMarshaler:: MarshalNatative ToManaged, 接收来自本地 Dll “ 胶片” 的正确数据, 该天体返回此天体 。
原标题:ICustomMarshaler::MarshalNativeToManaged, receiving correct data from native dll “looses” the object it returns
  • 时间:2012-05-24 21:01:55
  •  标签:
  • c#
  • pinvoke

我用我自己的元帅执行ICustom Marshaller 来操作本地(未管理的) dll C 功能。

函数“元元帅ToManage”中,我确实看到来自涂层的正确结果。问题在于“元帅”管理回报的物体没有“使用”。调用参数( In, Out)中的物体没有被修改。

(It looks like it is exactly the same problem that was previosly discussed here "C#: Object with custom marshaller not containing data after PInvoke call") 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);

在《元帅管理》中,我确实看到 调试功能的正确结果。

    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
    }

What am I doing wrong here? Just a quick note: I do want to know how to handle it using CustomMarshaler not "some other way around" :)

问题回答

OK 看来我知道现在是怎么回事了

The trick is that while dealing with Object we are dealing with pointers really (no matter how hard C# tries to hide that fact) and step by step: 1) hack(CMA* pCMA); 2) MarshalManagedToNative(void* pCMA) // C# passes the pointer we passed to hack here 3) Void* MarshalNativeToManaged(void *_some_PTR_to_memory_visible_to_managed_and_unmanaged_area) And here is the QUESTION what does .NET do with this Void* ptr that this function returns? If one does not use ref it has no way to change the object in the hack(cma). This pointer is simply not used anywhere. The function could have been void.

    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;

后来在元元帅管理时代

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

If we would use ref like this hack(ref CMA); // thanks to the previous answer BTW In this case it is hack(CMA**pp) and .NET does use the pointer we return from MarshalNativeToManaged *pp = oo;

底线是,我们要么必须保留我们的指针,改变它指向的内存值,要么(使用 ref)将指针传给指针(是旧的好**),并改变指针本身的价值。

C# 语言要求您声明一个参数为 ref out , 以允许它返回新的值。 修补 :

[DllImport("first.dll", EntryPoint = "hack")]
public static extern int hack(
    [In, Out]
    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ZMarshal))]
    ref CMA cma);




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签