C++ gerenciado de ponteiro para ponteiro
-
09-06-2019 - |
Pergunta
Eu tenho uma biblioteca C antiga com uma função que é nula **:
oldFunction(void** pStuff);
Estou tentando chamar essa função de C++ gerenciado (m_pStuff é membro da classe ref pai do tipo void*):
oldFunction( static_cast<sqlite3**>( &m_pStuff ) );
Isso me dá o seguinte erro do Visual Studio:
erro C2440:'static_cast':não é possível converter de 'cli::interior_ptr' para 'void **'
Suponho que o compilador esteja convertendo o ponteiro do membro void* em um cli::interior_ptr nas minhas costas.
Algum conselho sobre como fazer isso?
Solução
EDITAR:Resposta fixa, veja abaixo.
Realmente você precisa saber o que oldFunction fará com pStuff.Se pStuff for um ponteiro para alguns dados não gerenciados, você pode tentar agrupar a definição de m_pStuff com:
#pragma unmanaged
void* m_pStuff
#pragma managed
Isso tornará o ponteiro não gerenciado, que poderá então ser passado para funções não gerenciadas.É claro que você não poderá atribuir nenhum objeto gerenciado diretamente a este ponteiro.
Fundamentalmente, ponteiros não gerenciados e gerenciados não são iguais e não podem ser convertidos sem algum tipo de código cola que copie os dados subjacentes.Basicamente, os ponteiros gerenciados apontam para o heap gerenciado e, como ele é coletado como lixo, o endereço de memória real para o qual eles apontam pode mudar com o tempo.Ponteiros não gerenciados não alteram o endereço de memória sem que você faça isso explicitamente.
Risque isso, você não pode definir não gerenciado/gerenciado dentro de uma definição de classe.Mas este código de teste parece funcionar bem:
// 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;
}
Aqui, primeiro copio o ponteiro do objeto gerenciado e depois passo-o para oldFunction.Em seguida, copio o resultado (provavelmente atualizado por oldFunction) de volta para o objeto gerenciado.Como o objeto gerenciado está no heap gerenciado, o compilador não permitirá que você passe uma referência ao ponteiro contido nesse objeto, pois ele pode se mover quando o coletor de lixo for executado.
Outras dicas
Obrigado pelo conselho, o ponteiro é para uma estrutura abstrata de estilo C que acho que se eu deixar essa estrutura exposta ao código gerenciado causará mais problemas devido à falta de estrutura definida.Então, o que acho que farei é agrupar a biblioteca C em C++ e, em seguida, agrupar o wrapper C++ com C++ gerenciado, o que evitará a exposição dessas estruturas C ao código gerenciado.