对于某些方法,我们有一个带有以下简化IDL的遗留COM DLL:
AllocateMemory( [in] LONG lSize, [out] LONG *pAddr );
此方法的实现包含以下内容:
BYTE *pArr = (BYTE*)CoTaskMemAlloc( lSize );
*pAddr = &pArr;
新分配的内存的地址作为long值返回给调用者。
使用此COM对象的C ++客户端可以调用该方法,然后按如下方式访问内存:
//---- C++ ----------------
long lSize = 10;
long lAddr;
pCOMObj->AllocateMemory( lSize, &lAddr );
byte **bArray = (byte**)lAddr;
for (int i = 0; i < iSize; i++)
{
printf( "array[%d] = %d\n", i, (*bArray)[i] );
}
// Now deallocate memory.
CoTaskMemFree( *bArray );
//--------------------
一切都适用于C ++ COM客户端。
添加了相同的COM DLL作为Visual Studio 2010项目的引用 我们的目标是能够使用Interop从C#客户端执行相同的操作:
//---- C# ----------------
int iSize = 10;
int iAddr = 0;
objCOM.AllocateMemory( iSize, ref iAddr );
...
// ??? *UNKNOWN*
// At this point we need to be able to access allocated memory pointed to by iAddr.
// The following does NOT work, i.e., no errors occur but array contents are totally
// different from what has been initialized inside AllocateMemory() method, implying
// that totally different memory is being accessed/copied:
byte [] bArray = new byte [iSize];
IntPtr rAddr = new IntPtr( iAddr );
// Marshal the array from an unmanaged to a managed heap.
Marshal.Copy( rAddr, bArray, 0, iSize );
for (int i=0; i < iSize; i++)
Console.WriteLine( bArray[i] );
// Release the unmanaged array.
Marshal.FreeCoTaskMem( rAddr );
//--------------------
有没有人知道潜在的解决方案?
答案 0 :(得分:0)
首先,您必须只构建x86-代码将在64位上失败。其次,您必须使用unsafe
代码在C#中执行此类转换。
答案 1 :(得分:0)
IntPtr bAddr = new IntPtr( iAddr ); // bAddr = (byte**)iAddr
IntPtr rAddr = new IntPtr(Marshal.ReadInt32(bAddr)); //rAddr = (*bAddr);
byte [] bArray = new byte [iSize];
// Marshal the array from an unmanaged to a managed heap.
Marshal.Copy( rAddr, bArray, 0, iSize );
for (int i=0; i < iSize; i++)
Console.WriteLine( bArray[i] );
// Release the unmanaged array.
Marshal.FreeCoTaskMem( rAddr );
答案 2 :(得分:0)
有一个ReadIntPtr方法可从地址读取本机宽度指针。与ReadInt32不同,它将在两种体系结构上都能工作