指向指针托管的C ++的指针
时间:2020-03-05 18:43:04 来源:igfitidea点击:
我有一个旧的C库,带有一个需要作废**的函数:
oldFunction(void** pStuff);
我正在尝试从托管C ++调用此函数(m_pStuff是类型为void *的父引用类的成员):
oldFunction( static_cast<sqlite3**>( &m_pStuff ) );
这给了我来自Visual Studio的以下错误:
error C2440: 'static_cast' : cannot convert from 'cli::interior_ptr' to 'void **'
我猜编译器正在将void *成员指针转换为背后的cli :: interior_ptr。
有关如何执行此操作的任何建议?
解决方案
回答
编辑:固定答案,请参阅下文。
真的,我们需要知道pStuff将要使用的oldFunction。如果pStuff是指向某些非托管数据的指针,则可以尝试使用以下命令包装m_pStuff的定义:
#pragma unmanaged void* m_pStuff #pragma managed
这将使指针变为非托管指针,然后可以将其传递给非托管函数。当然,我们将无法直接将任何托管对象分配给此指针。
从根本上说,非托管指针和托管指针是不同的,并且如果没有某种复制基础数据的粘合代码就无法进行转换。基本上,托管指针指向托管堆,并且由于这是垃圾回收,因此它们指向的实际内存地址可能会随时间变化。未经管理的指针不会更改内存地址,除非我们明确地这样做。
请注意,我们不能在类定义内定义非托管/托管。但是此测试代码似乎可以正常工作:
// TestSol.cpp : main project file. #include "stdafx.h" using namespace System; #pragma unmanaged void oldFunction(void** pStuff) { return; } #pragma managed ref class Test { public: void* m_test; }; int main(array<System::String ^> ^args) { Console::WriteLine(L"Hello World"); Test^ test = gcnew Test(); void* pStuff = test->m_test; oldFunction(&pStuff); test->m_test = pStuff; return 0; }
在这里,我首先将指针从托管对象中复制出来,然后将其传递给oldFunction。然后,将结果(可能由oldFunction更新)复制回托管对象。由于托管对象位于托管堆上,因此编译器不允许我们传递对该对象中包含的指针的引用,因为当垃圾收集器运行时,该对象可能会移动。
回答
感谢建议,它的指针指向C风格的抽象结构,我认为,如果我将该结构暴露给托管代码,由于缺少定义的结构,这将导致进一步的痛苦。所以我想我要做的是将C库包装在C ++中,然后用托管C ++包装C ++包装器,这将防止将这些C结构暴露给托管代码。