IntPtr 未在单声道中正确编组

IntPtr is not properly marshaled in mono

我正在尝试在 Ubuntu 14.04 上使用 Mono 执行功能 P/Invoke:

[DllImport(@"libRT", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    private static extern uint DoChallenge(
        IntPtr pEncryptedBlob,
        uint dwEncryptedBlobLen,
        IntPtr pDecryptedBlob,
        uint dwMaxLen,
        ref uint dwDecryptedBlobLen);

在调用 C# 中的函数之前,我打印了加密和解密的值:

Console.WriteLine(pEncryptedBlob.ToString()); // value is 140640247632608
Console.WriteLine(pDecryptedBlob.ToString()); // values is 140640247634240

// Do the challenge
this.errorCode = DoRtasChallenge(pEncryptedBlob, pDecryptedBlob,
                    (uint)this.decryptedBlobBuffer.Length,
                    ref this.decryptedBlobReturnLength);

现在在 C++ 代码中打印我收到的值:

APIFUNC uint32_t DoChallenge(unsigned char * pEncryptedBlob,long dwEncryptedBlobLen,unsigned char * pDecryptedBlob,long dwMaxLen,long * dwDecryptedBlobLen)
{ 
    fprintf(stderr, "pEncryptedBlob: %ld \n",pEncryptedBlob);
    fprintf(stderr, "pDecryptedBlob: %ld \n",pDecryptedBlob);

    // the output: 
    // pEncryptedBlob: 1 
    // pDecryptedBlob: 140640603072256 
}

所以看起来两个 IntPtr 在编组期间都被修改了。

我假设这是因为 Mono/Ubuntu 14.04 64 位环境,因为它适用于 Windows 和 Ubuntu 14.04 32 位。

有什么解决方法吗?非常感谢

我刚刚找到了一个解决方法,我强制将我的 IntPtr 编组为 4 个字节:

[DllImport(@"libRT", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern uint DoChallenge(
    [MarshalAs(UnmanagedType.U4)] // this is a fix
    IntPtr pEncryptedBlob,
    uint dwEncryptedBlobLen,
    [MarshalAs(UnmanagedType.U4)]
    IntPtr pDecryptedBlob,
    uint dwMaxLen,
    ref uint dwDecryptedBlobLen);

结果:

C# 结果:

139700723537696
139700723538064

C++ 结果:

pEncryptedBlob: 139700723537696 
pDecryptedBlob: 139700723538064

要删除特定于平台的实现,以便您的 C# 和 c/cpp 代码将 运行 xplat,您应该将 C# "System.String" 传递给 "const char *src"。互操作编组将处理其余部分。

C 签名:

void myfunc (const char *src, size_t n);

C# Dll导入:

private static extern void myCfunc (string src, uint n);

用法:

var myString = "Test";
myCfunc(myString, myString.Length);

与本机库互操作: http://www.mono-project.com/docs/advanced/pinvoke/