我遇到了将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
。这有什么想法吗?
答案 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()