Сведения о вопросе

Htmlщик

03:53, 11th August, 2020

Теги

Указатель на указатель управляемый C++

Просмотров: 406   Ответов: 2

У меня есть старая библиотека C с функцией, которая принимает void**:

oldFunction(void** pStuff);

Я пытаюсь вызвать эту функцию из managed C++ (m_pStuff является членом родительского ref-класса типа void*):

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

Это дает мне следующую ошибку от Visual Studio:

ошибка C2440: 'static_cast': не удается преобразовать из 'cli::interior_ptr' в ' void **'

Я предполагаю, что компилятор преобразует указатель члена void* в cli::interior_ptr за моей спиной.

Есть какие-нибудь советы, как это сделать?



  Сведения об ответе

screen

14:07, 8th August, 2020

EDIT: исправлен ответ, см. ниже.

На самом деле вам нужно знать, что 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) обратно в управляемый объект. Поскольку управляемый объект находится в управляемой куче, компилятор не позволит вам передать ссылку на указатель, содержащийся в этом объекте, поскольку он может перемещаться при запуске сборщика мусора.


  Сведения об ответе

qwerty101

17:10, 6th August, 2020

Спасибо за совет, указатель находится на абстрактную структуру стиля C, которая, как я думаю, если я оставлю эту структуру открытой для управляемого кода, вызовет дополнительную боль из-за отсутствия определенной структуры. Поэтому я думаю, что сделаю следующее: оберну библиотеку C в C++ , а затем оберну оболочку C++ с управляемым C++, что предотвратит раскрытие этих структур C управляемому коду.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться