从C ++ / CLI指针转换为本机C ++指针

时间:2009-08-13 09:38:31

标签: c++-cli interop

我遇到了将C ++ / CLI指针转换为本机C ++指针的问题。继承人的背景: 我正在使用C ++ / CLI编写Windows窗体应用程序。该应用程序调用许多COM接口。当通过COM接口创建对象的实例(在C ++ / CLR类的内部)时,我将(void**)(&provider)作为CoCreateInstance的最后一个参数传递,如:

HRESULT CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider));

但是,我收到编译错误:无法从cli::interior_ptr<Type>转换为void **。 我已经对此进行了研究,看起来它是C ++和C ++ / CLI中不同类型指针的问题。任何人都对此有任何了解,也许有关如何修复它的提示? Thanx提前!

首先,感谢你的帮助!

正如Freich建议的那样,我尝试使用pin_ptr,但这反而让编译器抱怨从interior_ptr转换为pin_ptr的问题。如果我改为尝试使用interior_ptr,如:

pin_ptr<void *> pinnedPtr = &provider;
CoCreateInstance(CLSID_MSPRProvider, NULL, CLSCTX_LOCAL_SERVER, IID_IMSPRProvider, ( void** )pinnedPtr);

我无法从interior_ptr转换为interior_ptr。 这一切都归结为将interior_ptr转换为void**的问题。像这样:(void**)interiorPtr,其中interiorPtr当然是interior_ptr。这有什么想法吗?

3 个答案:

答案 0 :(得分:11)

我认为你必须将指针标记为'固定'(在托管代码中),然后将字节复制到某个非托管内存区域,然后使用指针指向它。例如,这里有一段代码,我曾经在某处将指向托管的System :: String的指针转换为UTF-8编码的非托管std :: string:

std::string managedStringToStlString( System::String ^s )
{
    Encoding ^u8 = Encoding::UTF8;
    array<unsigned char> ^bytes = u8->GetBytes( s );
    pin_ptr<unsigned char> pinnedPtr = &bytes[0];
    return string( (char*)pinnedPtr );
}

请注意我必须获得bytes函数返回的GetBytes()数组的“固定”指针,然后将其转换为char*,然后再将其传递给{ {1}}构造函数。我认为这是必要的,以避免托管内存子系统在我将字节复制到STL字符串时将std::string数组移动到内存中。

在您的情况下,请尝试替换

bytes

CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 

并查看是否有效。

答案 1 :(得分:4)

我使用C ++ / CLI已经有一段时间了,但我认为你必须固定指针。

答案 2 :(得分:4)

在调用CoCreateInstance()之后,指向的内存是否有效?

正如Frerich和Achim所提到的,你可以通过“固定”它并获得一个内部指针来获得一个指向内存的原始指针,而不用担心内存被重新定位。您通常使用pin_ptr模板执行此操作(有关示例,请参阅Frerich文章)。

但是,pin_ptr故意仅在堆栈上可用。您不能将其用作成员变量或全局变量,并且不能将其作为参数或返回值传递。当内存离开范围时,内存将被取消固定。

因此,如果只需要在调用CoCreateInstance()期间使内存有效,那么pin_ptr就是最佳选择。 如果没有,那么你将需要获取内存的副本并将 传递给CoCreateInstance()