C++ cli 从C+转换+/指向本机C++;指针 我已经遇到了将C++ /CLI指针转换为本地C++指针的问题。背景如下: 我正在使用C++/CLI编写一个windows窗体应用程序。应用程序调用许多COM接口。当通过COM接口创建对象的实例(在C++/CLR类内部)时,我将(void**)(&provider)作为最后一个参数传递给CoCreateInstance,如下所示: HRESULT CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider));

C++ cli 从C+转换+/指向本机C++;指针 我已经遇到了将C++ /CLI指针转换为本地C++指针的问题。背景如下: 我正在使用C++/CLI编写一个windows窗体应用程序。应用程序调用许多COM接口。当通过COM接口创建对象的实例(在C++/CLR类内部)时,我将(void**)(&provider)作为最后一个参数传递给CoCreateInstance,如下所示: HRESULT CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider));,c++-cli,interop,C++ Cli,Interop,但是,我得到了编译器错误:无法从cli::interior\u ptr转换到void**。 我已经做了一些研究,这看起来是C++和C++中CLI的不同类型的指针的问题。任何人都知道这一点,也许还有一点关于如何修复它的建议?先走一步 首先,谢谢你的帮助 正如Freich所建议的,我尝试使用pin\u ptr,但这反而使编译器抱怨从interior\u ptr转换到pin\u ptr时出现问题。如果我改为尝试使用内饰\u ptr,如中所示: pin_ptr<void *> pinnedP

但是,我得到了编译器错误:无法从
cli::interior\u ptr
转换到
void**
。 我已经做了一些研究,这看起来是C++和C++中CLI的不同类型的指针的问题。任何人都知道这一点,也许还有一点关于如何修复它的建议?先走一步

首先,谢谢你的帮助

正如Freich所建议的,我尝试使用
pin\u ptr
,但这反而使编译器抱怨从
interior\u ptr
转换到
pin\u ptr
时出现问题。如果我改为尝试使用
内饰\u ptr
,如中所示:

pin_ptr<void *> pinnedPtr = &provider;
CoCreateInstance(CLSID_MSPRProvider, NULL, CLSCTX_LOCAL_SERVER, IID_IMSPRProvider, ( void** )pinnedPtr);
pin\ptr pinnedPtr=&provider;
CoCreateInstance(CLSID_MSPRProvider,NULL,CLSCTX_LOCAL_服务器,IID_IMSPRProvider,(void**)pinnedPtr);
我无法从
interior\u ptr
转换到
interior\u ptr

这一切归结为将
内部ptr
转换为
无效**
的问题。这样:
(void**)interiorPtr
,其中
interiorPtr
当然是
interior\u ptr
。这方面有什么想法吗?

我使用C++/CLI已经很久了,但我认为您必须固定指针。

我认为您必须将指针标记为“固定”(在托管代码中),然后将字节复制到某个非托管内存区域,然后使用指向该区域的指针。例如,我曾经在某个地方找到一段代码,它将指向托管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 );
}

pin\ptr pinnedPtr=&provider;
协同创建实例(rclsid、pUnkOuter、dwClsContext、riid、(void**)pinnedPtr);

然后看看这是否有效。

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

正如Frerich和Achim所提到的,通过“固定”内存并获得内部指针,您可以获得指向内存的原始指针,而不必担心内存被重新定位。您通常使用pin_ptr模板来实现这一点(请参阅Frerich post以获取示例)

然而,pin_ptr故意只在堆栈上可用。不能将其用作成员变量或全局变量,也不能将其作为参数或返回值传递。当内存离开作用域时,它将被取消固定

因此,如果只需要在调用CoCreateInstance()期间内存才有效,那么pin_ptr就是一种方法。
如果没有,则必须获取内存副本并将其传递给CoCreateInstance()

有一个名为cli::pin_ptr的方便模板,这可能是OP需要的,因为它的设计目的是确保指向托管对象的指针不会被垃圾收集器移动。这似乎很危险!我以前也遇到过类似(或相同)的情况:我创建了一个固定指针并返回了本机指针(就像您所做的那样),但随后对象被移动,因为函数结束,固定指针被删除,因此对象不再固定,本机指针无效!这在调试过程中可能会出现,也可能不会出现,但可以肯定的是,当您不期望它出现时,它会出现在您的发布版本中。@TobiasKnauss
std::string::string(const char*)
构造函数会创建引用数据的副本,因此当函数退出时,如果引用的内存不再被固定,这是可以的。
CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 
pin_ptr<void *> pinnedPtr = &provider;
CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)pinnedPtr);