2016-05-31 12 views
0

Ich sehe seltsames Verhalten versuchen, C++ - und C-Code zu kombinieren. Ich benutze eine C++ - Klasse in C-Code mit static_cast mit einem void* an die Klasse. Dies geschieht auf folgende Weise.C++ Zeiger Wert ändert sich mit static_cast

//C++ code 
void* newCSPI() { 
    return static_cast<void*>(new XSpi); 
} 

Diese Funktion wird in der Kopfzeile wie folgt deklariert.

//C++ code 
extern "C" void* newCSPI(void); 

Ich kann dann die C++ Funktionen im C-Code aufrufen. Ein Beispiel für die Implementierung der anderen Funktionen ist unten zu sehen.

//C++ code 
void selectCSlave(void* spi) { 
    static_cast<SPI*>(spi)->selectSlave(); 
} 

Diese Funktion wird auch als extern "C" im Header deklariert.

Diese Casting-Funktion wird wie folgt implementiert.

//C++ code 
void SPI::selectSlave(void) { 
    // Select the slave by setting the slave select to low 
    XGpio_DiscreteWrite(&slaveSelectDevice, 1, 0x00); 
} 

Ich versuche, den folgenden Codeblock auszuführen. Alles gelingt, bis auf die allerletzte Zeile.

//C code 

void* spi = newCSPI(); 

/* Select device. */ 
selectCSlave(spi); 

/* Transfer data over SPI*/ 
transferC(spi, MOSI, MISO, ByteNum); 

// It breaks here // 

/* Transfer data over SPI*/ 
transferC(spi, MOSI, MISO, ByteNum); 

/* Un-select device. */ 
deselectCSlave(spi); 

Während des zweiten transferC(spi) Aufruf ändert sich der Zeiger irgendwie Wert. Innerhalb der Darstellungsfunktion hat der Zeiger immer noch denselben Wert. Innerhalb der Funktion, in die es umgewandelt wird, ändert sich der Wert. Die Implementierung ist genau die gleiche wie die erste transferC(spi), die funktioniert. Zwischen diesen beiden Aufrufen gibt es keinen Code.

Ich kann nicht sehen, warum der Wert plötzlich ändern würde. Was fehlt mir hier?

Der Code für deselectCSlave() und SPI::deselectSlave(void):

void deselectCSlave(void* Cspi) { 
    static_cast<SPI*>(Cspi)->deselectSlave(); 
} 

void SPI::deselectSlave(void) { 
    // Deselects the slave by setting the slave select to high 
    XGpio_DiscreteWrite(&slaveSelectDevice, 1, 0xFF); 
} 

Die 0x00 und 0xFF die Werte geschrieben werden.

+0

Haben Sie noch nicht alles gelesen, aber Sie können eine undurchsichtige Struct-Definition für den Typedef verwenden, ersparen Sie sich eine Menge Casting in Ihrer Implementierung. – StoryTeller

+2

Bitte geben Sie eine [mcve] an.Außerdem ist es sehr verwirrend, eine Typedef für 'void *' zu haben - besonders wenn 'CSPI'' void * 'ist, aber' SPI' ist eigentlich ein Typ. – Barry

+0

Was lässt Sie denken, dass sich der Wert ändert? Erzählst du vom Debugger? Vielleicht zeigt der Debugger das Falsche an. Funktioniert der Code noch? – KABoissonneault

Antwort

2

Wenn Sie einen Zeiger auf void* werfen, die nur für die Umwertung Sie erlaubt sind auf diesen Wert zu tun ist, zurück in den spezifischen Typ, von dem Sie auf ein void* umgewandelt (na ja, können Sie es auch zu einem Guss char*). So

, wenn Sie dies tun:

return static_cast<void*>(new XSpi); 

Die einzige Möglichkeit, dass die Guss rückgängig machen kann, ist, indem es XSpi* Gießen. Daher Ihre spätere Besetzung:

static_cast<SPI*>(spi)->selectSlave(); 

Das ist illegal.

Was möchten Sie wahrscheinlich ist, dies zu tun:

return static_cast<void*>(static_cast<SPI*>(new XSpi)); 

dass sie erste konvertieren auf die Basisklasse (vermutlich SPI), dann wandle ihn zu void*.

+0

Das gibt den folgenden Fehler: 'ungültiges static_cast vom Typ XSpi * zu type SPI *' – Etruscian

+2

@Etruscian: Der einzige Grund, der ungültig wäre, wäre, wenn 'SPI' und' XSpi' zwei * völlig unabhängige * Klassen wären. Das heißt, 'SPI' ist nicht die Basis von' XSpi'. Ich habe deine Frage so beantwortet, wie es nur funktionieren könnte. Sie sagen, dass Ihr Code grundsätzlich dysfunktional ist. Wenn dein Code nicht kaputt ist, poste bitte * deinen Code als * mcve, damit wir sehen können, was vor sich geht. –

+0

Sollte aber ein dynamic_cast zwischen SPI * und XSpi * sein, wenn einer von dem anderen – sokkyoku

Verwandte Themen