Frage

Ich habe eine alte C-Bibliothek mit einer Funktion, die eine Lücke benötigt**:

oldFunction(void** pStuff);

Ich versuche, diese Funktion aus verwaltetem C++ aufzurufen (m_pStuff ist ein Mitglied der übergeordneten Referenzklasse vom Typ void*):

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

Dies gibt mir den folgenden Fehler von Visual Studio:

Fehler C2440:'static_cast':Konvertierung von „cli::interior_ptr“ nach „void **“ nicht möglich.

Ich vermute, dass der Compiler hinter meinem Rücken den void*-Mitgliedszeiger in einen cli::interior_ptr konvertiert.

Irgendwelche Ratschläge, wie man das macht?

War es hilfreich?

Lösung

BEARBEITEN:Feste Antwort, siehe unten.

Sie müssen wirklich wissen, was oldFunction mit pStuff machen wird.Wenn pStuff ein Zeiger auf einige nicht verwaltete Daten ist, können Sie versuchen, die Definition von m_pStuff mit Folgendem zu umschließen:

#pragma unmanaged

void* m_pStuff

#pragma managed

Dadurch wird der Zeiger nicht verwaltet, der dann an nicht verwaltete Funktionen übergeben werden kann.Natürlich können Sie diesem Zeiger keine verwalteten Objekte direkt zuweisen.

Grundsätzlich sind nicht verwaltete und verwaltete Zeiger nicht dasselbe und können nicht ohne eine Art Klebecode konvertiert werden, der die zugrunde liegenden Daten kopiert.Grundsätzlich verweisen verwaltete Zeiger auf den verwalteten Heap, und da es sich hierbei um Garbage Collection handelt, kann sich die tatsächliche Speicheradresse, auf die sie verweisen, im Laufe der Zeit ändern.Nicht verwaltete Zeiger ändern die Speicheradresse nicht, ohne dass Sie dies ausdrücklich tun.

Vergessen Sie nicht, dass Sie nicht verwaltet/verwaltet innerhalb einer Klassendefinition definieren können.Aber dieser Testcode scheint einwandfrei zu funktionieren:

// 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;
}

Hier kopiere ich zuerst den Zeiger aus dem verwalteten Objekt und übergebe ihn dann an die oldFunction.Dann kopiere ich das Ergebnis (wahrscheinlich aktualisiert von oldFunction) zurück in das verwaltete Objekt.Da sich das verwaltete Objekt auf dem verwalteten Heap befindet, lässt der Compiler nicht zu, dass Sie einen Verweis auf den in diesem Objekt enthaltenen Zeiger übergeben, da dieser sich möglicherweise bewegt, wenn der Garbage Collector ausgeführt wird.

Andere Tipps

Vielen Dank für den Rat, der Zeiger verweist auf eine abstrakte Struktur im C-Stil. Ich denke, wenn ich diese Struktur dem verwalteten Code ausgesetzt lasse, wird dies aufgrund des Fehlens einer definierten Struktur zu weiteren Problemen führen.Ich denke also, ich werde die C-Bibliothek in C++ einschließen und dann den C++-Wrapper mit verwaltetem C++ umschließen, wodurch verhindert wird, dass diese C-Strukturen verwaltetem Code ausgesetzt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top