2008-08-25 325 views
1

我有一个旧的C库,需要一个无效**功能:指针指向托管C++

oldFunction(void** pStuff); 

我试图从托管C调用此函数++(m_pStuff是父成员引用类类型为void *的):

oldFunction(static_cast<sqlite3**>( &m_pStuff)); 

这让我从Visual Studio以下错误:

错误C2440:'的static_cast:不能CONVER从'cli :: interior_ptr'到'void **'

我在猜测编译器正在将void *成员指针转换为背后的cli :: interior_ptr。

有关如何做到这一点的任何建议?

回答

1

编辑:修复答案,见下文。

真的,你需要知道什么oldFunction将与pStuff做什么。如果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更新)复制回管理对象。由于托管对象位于托管堆上,因此编译器不会让您传递对象中包含的指针的引用,因为它可能在垃圾收集器运行时移动。

0

感谢您的建议,指针指向C风格的抽象结构,我认为如果我将该结构暴露给托管代码,由于缺少定义的结构会导致进一步的痛苦。所以我想我会做的是用C++封装C库,然后用托管C++封装C++封装,这将防止将这些C结构暴露给托管代码。