【问题标题】:Pointer to Pointer Managed C++指向指针托管 C++ 的指针
【发布时间】:2008-08-25 22:55:48
【问题描述】:

我有一个旧的 C 库,其函数采用 void**:

oldFunction(void** pStuff);

我正在尝试从托管 C++ 调用此函数(m_pStuff 是 void* 类型的父 ref 类的成员):

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

这给了我来自 Visual Studio 的以下错误:

错误 C2440:“static_cast”:无法从“cli::interior_ptr”转换为“void **”

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

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

【问题讨论】:

    标签: pointers managed-c++


    【解决方案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 更新)复制回托管对象。由于托管对象位于托管堆上,因此编译器不会让您传递对该对象中包含的指针的引用,因为它可能会在垃圾收集器运行时移动。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 1970-01-01
        • 1970-01-01
        • 2017-06-21
        • 1970-01-01
        • 2016-10-09
        • 2021-08-14
        相关资源
        最近更新 更多