编组人员对自定义封送器对返回值的期望是什么?

时间:2013-02-26 16:20:29

标签: c# marshalling pass-by-value

我正在尝试为C#委托返回值

实现自定义封送程序
[return: MarshalAs(UnmanagedType.CustomMarshaler,MarshalType = "MyCustomMarshaler")]
public delegate MSyntax SyntaxCreator();

在C ++中,MSyntax类型是普通的C ++类。

在C#中,MSyntax类型是一个普通的C#类(不是结构),它有一个内部指针(使用IntPtr)到C ++类。

所以我写了像MarshalManagedToNative这样的方法:

public IntPtr MarshalManagedToNative(Object ManagedObj)
{
    MSyntax msyntax = ManagedObj as MSyntax;
    // GetNativeDataSize() returns what sizeof(MSyntax) returns in C++
    IntPtr ptrBlock = Marshal.AllocCoTaskMem( GetNativeDataSize() );

    unsafe
    {
        byte* ptrDest = (byte *)ptrBlock.ToPointer();
        byte* ptrSource = (byte *)msyntax.GetInternalCPlusPlusPointer();
        for( uint i = 0; i < GetNativeDataSize(); ++i )
        {
            *ptrDest = *ptrSource;
            ++ptrDest;
            ++ptrSource;
        }
    }
    return ptrBlock;
}

正如您所看到的,它使用Marshal.AllocCoTaskMem分配足够的内存来保存C ++ MSyntax的新实例,然后将内部C ++ MSyntax的内容从ManagedObj复制到这个新实例。

它几乎可以工作。 在C ++中,此委托/回调函数的调用者执行以下操作:

MSyntax syntax = CallCallbackFunction();

在正常的C ++中执行此行时,C ++创建一个新的MSyntax实例,调用MSyntax的复制构造函数,传递对“CallCallbackFunction()”返回的MSyntax的引用,然后调用该引用的析构函数,因为它是一个中间体值(可能在堆栈上)。

现在在我的情况下,调用最终调用我的MarshalManagedToNative方法,返回时,相应地调用MSyntax的C ++拷贝构造函数并且工作正常。如果我调试它,我可以看到传递给复制构造函数的引用是我从MarshalManagedToNative方法返回的IntPtr,所以这很好。但最后MSyntax的析构函数被称为,但是“this”指针是错误的,所以它失败了...... “this”指针不是我从MarshalManagedToNative方法返回的IntPtr ...它可能是堆栈上的地址......难怪。

所以我想知道如何实现MarshalManagedToNative方法以使此代码正常工作? (顺便说一句,我在win64上,所以这是使用的快速调用约定。)

在浏览网页时,我发现编组人员对定制编组人员有一些特殊的期望。例如,如果您有这样的方法:

void foo( [in: MarshalAs(UnmanagedType.CustomMarshaler,MarshalType = "MyCustomMarshaler")] SomeClass * arg );

编组程序将从您的MarshalManagedToNative方法返回IntPtr并期望首先在此内存地址处找到一个整数,该整数表示整数后有多少SomeClass元素(因为SomeClass *指针参数可能是一个数组)。 / p>

你们知道这些文件记录在哪里吗?很抱歉,但我找不到它:-(
我希望找到一些特殊的信息来决定我应该如何实现MarshalManagedToNative方法。

由于

0 个答案:

没有答案