【问题标题】:Convert from C++/CLI pointer to native C++ pointer从 C++/CLI 指针转换为本机 C++ 指针
【发布时间】:2010-11-19 06:03:40
【问题描述】:

我遇到了将 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 中不同类型指针的问题。任何人都对此有任何了解,也许有关于如何修复它的提示?提前谢谢!

首先,感谢您的帮助!

正如 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。有什么想法吗?

【问题讨论】:

    标签: c++-cli interop


    【解决方案1】:

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

    【讨论】:

    • 有一个名为 cli::pin_ptr 的便捷模板可能是 OP 需要的,因为它旨在确保垃圾收集器不会移动指向托管对象的指针。
    【解决方案2】:

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

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

    在你的情况下,尝试替换

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

    pin_ptr<void *> pinnedPtr = &provider;
    CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)pinnedPtr); 
    

    看看这是否有效。

    【讨论】:

    • 这似乎很危险!我之前遇到过类似(或相同)的情况:我创建了一个固定指针并返回了本机指针(就像你一样),但随后对象被移动,因为函数结束并且固定指针被删除,所以对象不再固定并且本机指针无效!在调试过程中可能会看到也可能不会看到,但肯定会在您不期望的时候发生在您的发布版本中。
    • @TobiasKnauss std::string::string(const char *) 构造函数会创建引用数据的副本,因此如果函数退出时不再固定引用的内存也没关系。
    【解决方案3】:

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

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

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

    因此,如果内存只需要在调用 CoCreateInstance() 期间有效,那么 pin_ptr 就是要走的路。 如果没有,那么您将不得不获取内存的副本并将 that 传递给 CoCreateInstance()

    【讨论】:

      猜你喜欢
      • 2016-08-24
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多