Re: C++ stream in variable referenzieren

Konrad Rosenbaum <[email protected]> Wed, 3 Apr 2024 15:21:47 +0200
Newsgroups gmane.user-groups.linux.dresden
Message-ID <[email protected]>
Hi,


On 02/04/2024 21:54, Sebastian Reinhardt wrote:
> Ich steh mal wieder etwas auf dem Schlauch und ich hoffe, dass mir 
> einer von euch den "Schubs" in die richtige Richtung geben kann.

Willkommen auf dem Schlauch. Beim Abstieg bitte Vorsicht, es sind Knoten 
an unerwarteten Stellen...


> Erstmal die Voraussetzungen:
>
> Ich habe an einem PC/PI mehrere I2C-GPIO- Porterweiterungen (MCP23017 
> und MCP23008) hängen. Die haben 16 bzw. 8 GPIO's und hängen mit 
> verschiedenen Adressen am I2C.
>
> Nun möchte ich diese Bausteine mit C++ über I2C mit entsprechenden 
> Bibliotheken (MCP23017 und MCP23008) direkt ansteuern. Die jeweilige 
> Bezeichnung, Busadresse usw. lese ich aus einer text/csv-DAtei ein und 
> rufe diese Daten aus der Vectorvariable (mcp_elements mit eigener 
> struct) ab. Das funktioniert soweit auch, z.B.:
>
> -------code-------
>
> MCP23017 mcpout1.(atoi(mcp_elements[i_e].busnr.c_str()), 
> atoi(mcp_elements[i_e].busaddr.c_str()));
>
> mcpout1.openI2C();
>
> for ( int i17 = 0; i17 < 16; i17++) {
>
>     mcpout1.pinMode(i17, OUTPUT);
>     mcpout1.pinMode(i17, LOW);
>
> }
>
> -------/code-------
>
> Nun muss ich eben für jeden Baustein  das Device mit dem 
> Handle/ostream verbinden und benötige eben z.B. "mcpout1", "mcpout2", 
> "mcpout3" usw. Da ich aber nicht sicher weiss, ob immer die gleiche 
> Anzahl von I2C- Bausteinen an den Bus angeschlossen sind, ist diese 
> "Hardcodierung" ungünstig. Um nicht jedes mal das Programm anpassen 
> und neu kompilieren zu müssen, möchte ich die Art (MCP23008/MCP23017), 
> Busadresse, Art der Ports (In-/Outputs) Nummerierung der Ports usw. 
> aus der txt/csv-Datei lesen und das etwas dynamisch behandeln. Das 
> Lesen der Infos klappt schon, aber dann hänge ich....

Ohne zu wissen wie das alles unter der Haube funktioniert ist der Rest 
dieser Mail eher spekulativ.


> Nun die Frage: Kann ich eine Variable (event. einen Vector) erstellen 
> in den ich dann in einer Zeile "Nr", "Streamref", "Portnummerstart", 
> "Portnummerende" speichern kann und dann eben nur diese eine Variable 
> in die anderen Unterprogramme übergeben kann? D.h., kann ich in dieser 
> Variable, und wenn ja wie, die Streamreferenz speichern und übergeben 
> kann. In den Unterprogrammen möchte ich die Variable nach dem Schema 
> "liegt die anzusteuernde Portnummer zwischen "Start" und "Ende", dann 
> ist der Stream/ Referenz zu verwenden benutzen.

Natürlich kannst Du komplexe Strukturen/Klassen mit Referenzen bauen und 
übergeben. Wir reden hier über C++, da geht sowas.

Profi-Tip: übergib diese Variable als "const MyClass&" an 
Unterfunktionen - das geht schneller/effizienter (nur ein Pointer auf 
dem Stack statt einer Kopie der Struktur). Im Vektor bitte als volle 
Kopie, sonst gibt es schnell Probleme.


> Wie müsste die Variable aussehen? Vector mit welcher struct?

Vector ist gut. Struct ist reichlich veraltet - benutz' doch einfach 
C++! ;-)

Bei sowas baue ich mir gerne kleine Helferklassen. Zum Beispiel:

class McpOutRef {
     MCP23017 &ref;
     int start=0,end=0;
public:
     McpOutRef(MCP23017&aref,int astart,int 
aend):ref(aref),start(astart),end(aend){}
     McpOutRef(const McpOutRef&)=default;
     McpOutRef(McpOutRef&&)=default;

     McpOutRef& operator=(const McpOutRef&)=default;
     McpOutRef& operator=(McpOutRef&&)=default;

     bool containsPort(int port)const{return astart<=port && aend>=port;}

     MCP23017& mcp()const{return ref;}

};

Über containsPort könntest Du abfragen ob der gesuchte Port zu dieser 
Instanz gehört und über mcp() bekommst Du die Referenz.

Wenn man intern Pointer und extern Referenz benutzt, dann kann man noch 
etwas mehr "Magie" machen (z.B. saubere "Null-Refs"), aber das führt 
hier zu weit.

Du kannst Dir auch den Vektor erweitern:

class McpRefVector: public std::vector<McpOutRef> {

     bool hasPort(int port){
         for ( const auto&elem : *this) if(elem.containsPort(port)) 
return true;
         return false;
     }

     McpOutRef& byPort(int port) { .... }

}

Es fehlt noch etwas "Boilerplate" für Constructor, etc. ...


Falls Dein Compiler sich über && oder =default beschwert: -std=c++17 - 
wir sind ja nicht mehr im finsteren Mittelalter! ;-)


> Wäre toll, wenn mich jemand erleuchten könnte.....oder wenigstens den 
> Weg weisen könnte.

Hell genug?



     Konrad
OpenPGP_0xBE96A6EE776FE5D0.asc (application/pgp-keys, 2.6 KB)
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
GITvFOoOgCafGm48BZJcCkN1rLBx
=eE4a
-----END PGP PUBLIC KEY BLOCK-----
OpenPGP_signature.asc (application/pgp-signature, 495 B)
-----BEGIN PGP SIGNATURE-----

wsB5BAABCAAjFiEEjkC056IhcKJYJr8GxU4Frrk6fnUFAmYNV+sFAwAAAAAACgkQxU4Frrk6fnW9
1QgAxkiWe9GkVrzyO5DxFb17nPea9E6SS9UGffyHBWxOmmHYMQM5XqtggoZzJpycC1V7B8g41qwW
xsByt2vXwptwe2e6yNG8p0l6xva8HY5S0+CsHzsmtfK9VZ8YJoyBvmg7BASodvp2WX9v2naHM27M
DA8GR4rgJiDGlki8eDCc9RitzeQ3GNRRB1D1eKLT6GfROqEG/RJf4FUTjY0iJEwfF/L10/5/uslv
+1PN5P6CIexw9pvfteZs3z8PNtaOOtipJCn88j8Grb+swoVVar0GReAtX7FNWEhT/7CTriZYYLOl
WBU3Gyj5Z4Ec1F2X2upNSAtwTi4j6zEZFC8QjCv9VA==
=LQ/s
-----END PGP SIGNATURE-----