[C++] Welche Instanz ruft Funktion auf?

DexXxtrin

Erfahrenes Mitglied
Hallo Zusammen

Ist es möglich im C++ (Gnu Compiler für ARM, C++11 o. 14) heraus zu finden, welche Instanz eine Funktion aufgerufen hat (auf "einfache" Art und Weise)?

Noch kurz mein Problem beschrieben, dass Ihr wisst, wieso ich das will. Evtl gibt es ja auch elegantere Lösungen.
Ich bin an einer Firmware, bei der ich verschiedene Kommunikationskanäle habe (UART, BT, SPI,...).
An jedem Kommunikationskanal sind verschiedene Komponenten angeschlossen. Jeder Kommunikationskanal wird durch eine Klasse abstrahiert und können jeweils nur einmal Instanziert werden (da es den Kanal auch jeweils nur einmal geben kann). Die Komponenten sind jeweils auch durch eine Klasse abstrahiert und können so häufig instanziert werden, wie sie effektiv vorhanden sind (bekannt bevor Kompiliert wird).
Nun kann es aber mehrere z.b. SPI Busse haben, was mit allen anderen defines in einem Plattform Header definiert wird. Wissen, welche komponente an welchem Bus ist, soll nur dieser Header. Was heisst, dass die Komponenten dort beim jeweiligen Bus "registriert" werden.
Nun möchte ich, dass wenn ein Komponent über SPI kommunizieren will, einfach eine entsprechende Funktion der SPI-Klasse aufrufen kann, die funktion schaut, von welcher Instanz der Aufruf kommt und dann die Befehle über den entsprechenden Bus versendet.
Die Lösung soll halt so gemacht sein, dass verschiedene Geräte den selben Code verwenden können und nur jeweils der Header ausgetaust werden muss, welche Komponenten an welchen Kanälen angeschlossen sind.

Gruss DexXxtrin
 

cwriter

Erfahrenes Mitglied
Ich habe nur ein vages Bild im Kopf, wie deine Situation aussieht.

Also ich nehme als Gerät mal sowas in Richtung RPi oder (starker) Mikrocontroller an.
Ich verstehe aber nicht ganz, was du mit Komponenten meinst. Ein am Bus angeschlossenes Gerät kann man ja in aller Regel nicht programmieren, sondern empfängt Befehle und gibt Antworten (SPI ist ja Master-Slave).
Falls es nur darum geht, bei jedem Gerät zu wissen, an welchem Bus es hängt, ist wohl sowas wie
C++:
class Peripheral
{
public:
    Peripheral(Bus& owner, int select) : m_owner(owner), m_ss(select)
    {

    }
   
    void write(char* data, size_t len)
    {
        while(!Bus.ready()) std::this_thread::yield(); //Warten auf den Bus
        Bus.select(m_ss);
        Bus.write(data, len);
    }

    //Read similar

private:
    Bus& m_owner;
    int m_ss; //Slave select (Chip Select) line
};
am besten geeignet, sodass ein Schreiben an ein Peripheral immer automatisch den richtigen Bus / richtige CS-lines nimmt.

Um auf die eigentliche Frage einzugehen:
Ist es möglich im C++ (Gnu Compiler für ARM, C++11 o. 14) heraus zu finden, welche Instanz eine Funktion aufgerufen hat (auf "einfache" Art und Weise)?
Am allereinfachsten: Instanz als Funktionsparameter mitgeben.
Alternativ: Instanz implizit per static angeben (kann ziemlichen Spaghetticode ergeben und erfordert ebenfalls ein bisschen Code):
C++:
class Caller
{
public:
    
    void call()
    {
        lastCaller = this;
        Callee::func();
    }

    static Caller* lastCaller;
};
Da du auf offenbar wenig potenter Hardware arbeitest, wäre ein Einsparen von teurer Runtime wohl auch nicht schlecht.
Da du mit Headern arbeiten willst, wären Template-Funktionen wahrscheinlich auch nicht schlecht geeignet.
Allerdings: Ohne die genauere Codestruktur zu kennen, wird es relativ schwierig.

Natürlich kannst du mit Stacktraces arbeiten, aber auch das ist nicht wirklich effizient.
Also, um es kurz und knackig zu halten:
Nein, es ist nicht auf einfachste Art und Weise möglich, den Caller zu ermitteln.

Gruss
cwriter
 

DexXxtrin

Erfahrenes Mitglied
Besten Dank für deine Antwort.
Mit Komponente ist die Abstrahierung eines am SPI Bus angehängten z.B. Sensors gemeint. Wenn als ein g-Sensor am SPI Bus ist, existiert eine Klasse für diesen Sensor, so dass ich von meinen Routinen nur ein Funktion aufrufen kann um an die Daten zu kommen und kommunikation wird dann in der Klasse gemanaged.

Deine Annahme zur Einsparung von teurer Runtime ist natürlich korrekt, da das ganze in einem akkubetriebenen Gerät läuft.

Ich habe nun eine Lösung gewählt, welche deinem ersten Codeschnipsel ähnelt. Für jeden Kommunikationskanal (SPI Bus, I2C, UART,...) wird eine Instanz erzeugt. Die Komponenten erhalten bei der Instanzierung jeweils den Pointer zum Kommunikationskanal mit.
Denke das ist die einfachste und klarste Lösung.

Gruss DexXxtrin