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);
我正在尝试在 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);