Library Aufruf in header und cpp auslagern

Hallo leute.
Ich hab da eine library geschrieben und die läuft super wenn ich den constructor in der .ino Datei aufrufe. Ausgelagert in eine .h und .cpp datei meckert aber der Compiler

115:2: error: 'AHT' was not declared in this scope
AHT.begin()

sobald eine Methode aufgerufen wird.

in die .h Datei kommt das

#ifndef _VARIANTS_h
#define _VARIANTS_h
#include <AHT20_lib.h>
#endif

in die .cpp Datei

#include "variants.h"
AHT20 AHT;

Eigentlich müsste das doch gehen, aber offensichtlich habe ich da was nicht verstanden

Das gehört in den Anwendungscode, nicht in die Bibliothek.

Ausnahmen sind singletons wie Serial, Wire usw., dort gehören diese Definitionen in den Header.

Warum hältst du die Fehler verursachende Stelle geheim?
Dein Code ist bis zur Untestbarkeit verstümmelt.

Diese sind keine Singletons!
Es kann durchaus mehrere Instanzen von HardwareSerial und TwoWire geben.
Das wäre bei einem Singleton nicht möglich.

Ich halte es allerdings auch für bedenklich, bis falsch, wie das bei Arduino manchmal gehandhabt wird. Gerade bei den von dir genannten Instanzen.

Ich vermute, dass hier sowas gewünscht wird:

A.cpp (24 Bytes)
A.h (107 Bytes)
A_Test.ino (174 Bytes)

(auch wenn ich es für arg bedenklich halte)

1 Like

Solche "quasi-Singletons" haben bei Arduino auch gerne Großbuchstaben am Variablennamen-Anfang (z.B. Serial)
Aber "dass hier sowas gewünscht wird", denke ich auch.

Das
extern AHT20 AHT;
in der include Datei zu vergessen könnte das Problem sein, sagt meine Glaskugel.

Danke euch für die Antworten

Gestern hatte ich schon einen ganzen Roman zusammen......Mein Code zieht sich über viele Dateien und dazu noch mehrere eigene Librarys.
Hab dann doch versucht den Post kurz zu halten :upside_down_face:
ich versuchs in einem Satz:
Ich hab eine Funkplatine die ich unterschiedlich mit bestücken kann und je nach "Variante"braucht es andere Librarys und arrays die ich grad versuche über Präprozessordirekiven zu definieren, was im main code klappt, aber super unübersichtlich ist und ich somit gerne in eine andere Datei auslagern würde um mich nicht mit 6 Kopien des eigentlich gleichen Codes rumschlagen zu müssen .
z.B.

#ifdef VARIANT_bulbT_airT_groundT_watermark
	#include <ds18b20_lib.h>
	#include <AHT20_lib.h>
	#include "Watermark.h"
	ds18b20 tempSensorBulb (bulbTempPin);
	ds18b20 tempSensorGround(soilTempPin);
	AHT20 AHT;
	watermark watermarkSensor(watermark_digital_A, watermark_digital_B, watermark_analog_A, watermark_analog_B, digital2, num_read);

	struct dataStruct {
		float airTemperature;
		int8_t groundTemperature;
		float bulbTemperature;
		uint8_t watermark;
	} myData;

	struct payloadstruct{
		uint8_t pl_airTemperature_0;
		uint8_t pl_airTemperature_1;
		uint8_t pl_groundTemperature;
		uint8_t pl_bulbTemperature_0;
		uint8_t pl_bulbTemperature_1;
		uint8_t pl_watermark;
	} myPayload;

#endif

Also, das mit extern klappt mal... mal einlesen was das für nebenwirkungen hat.....
Vielen Vielen Dank euch allen

Extern an sich ist nicht böse, es ist nur die öffentliche Fixierung eines vorhergehenden "******".
Hier kommen Vorlieben ins Spiel!

Eins meiner Ziele ist, die Dinge tief in Geltungsbereiche zu versenken.
Hat man viele Dinge im aktuellen Geltungsbereich, kann es Namenskollisionen geben, z.B. Libraries welche den gleichen Bezeichner für unterschiedliche Dinge nutzen, oder eben z.B. Wire nutzen, man selber aber Wire1 damit beauftragen möchte.
Globale Variablen sind auf diese Art eher "sperrig".

Das war jetzt super :slightly_smiling_face:
Die structs werden auch schön weitergereicht
Jetzt hakts aber noch mal. Bis jetzt habe ich folgendes:
in der .h file:

#ifndef _VARIANTS_h
#define _VARIANTS_h

#include <AHT20_lib.h>
#include <ds18b20_lib.h>

extern AHT20 AHT;

//extern ds18b20 tempSensorBulb (18);
//extern ds18b20 tempSensorGround(17);

//extern ds18b20 tempSensorBulb(int airPin);
//extern ds18b20 tempSensorGround(int groundPin);

struct dataStruct {
	float airTemperature;
	int8_t groundTemperature;
	float bulbTemperature;
	uint8_t watermark;
};

extern struct dataStruct myData;

struct payloadstruct{
	uint8_t pl_airTemperature_0;
	uint8_t pl_airTemperature_1;
	uint8_t pl_groundTemperature;
	uint8_t pl_bulbTemperature_0;
	uint8_t pl_bulbTemperature_1;
	uint8_t pl_watermark;
};

extern struct payloadstruct myPayload;
#endif

und in der .cpp file:

#include "variants.h"

AHT20 AHT;

//ds18b20 tempSensorBulb(18);
//ds18b20 tempSensorGround(17);

struct dataStruct myData={
	.airTemperature = 0,
	.groundTemperature = 0,
	.bulbTemperature = 0,
	.watermark = 0
	};
	
struct payloadstruct myPayload={
	.pl_airTemperature_0 = 0,
	.pl_airTemperature_1 = 0,
	.pl_groundTemperature = 0,
	.pl_bulbTemperature_0 = 0,
	.pl_bulbTemperature_1 = 0,
	.pl_watermark = 0
	};

Mit dem AHT20 Sensor hats gleich geklappt.
Mit den ds18b20 Sensoren krieg ich den "multiple definition of tempSensorBulb" linker Fehler wenn ich den Pin direkt im Aufruf der Funktion einsetze. Also habe ich versucht Deklaration i .h und Definition in .cpp auszulagern aber irgendwie verstehe ich nicht wie ich da eine Logik rein kriege.

Hab alles auskommentiert was nicht funktioniert

Danke nochmal

Wo wird denn Zugriff auf diese (und die anderen) globalen Variablen benötigt? Das dürfte IMO der eigentliche Fehler sein.

In der Bibliothek sollte der deklarierte Datentyp reichen um Klassenelemente zu definieren.

Unterscheide zwischen Deklaration und Definition

// *.h
extern ds18b20 tempSensorBulb;
extern ds18b20 tempSensorGround;
// *.cpp
ds18b20 tempSensorBulb {18};
ds18b20 tempSensorGround {17};

extern struct dataStruct myData;
Was macht das Wort struct da?
Tipp: Du bist in C++ und nicht in C.

Das ist keine Funktion, das sieht nur so aus.

Die structs sind für die Payload, haben sonst nichts mit den bibliotheken zu tun, werd sie wahrscheinlich auch gegen arrays umtauschen

Sorry hab da konfusion reingebracht!

extern ds18b20 tempSensorBulb (18);
extern ds18b20 tempSensorGround(17);

aber hier wird schon definert(so hab ichs verstanden), also hab ich versucht erst in der .cpp zu definieren, was nicht geklappt hat.

//.h
extern ds18b20 tempSensorBulb(int airPin);
extern ds18b20 tempSensorGround(int groundPin);
//.cpp
ds18b20 tempSensorBulb(18);
ds18b20 tempSensorGround(17);

Warum zeige ich dir das richtige, wenn du dann doch wieder das falsche plapperst.....

struct geht doch bei beiden???

.

Wenn es an der Stelle überflüssig ist, dann ist es falsch, schon alleine weil es keiner so tut.
Es widerspricht dem Prinzip der geringsten Verwunderung.

Jetzt hab ichs gesehen :slightly_smiling_face: :slightly_smiling_face: :slightly_smiling_face:
Die geschwungenen Klammern sinds! Danke Danke
und es läuft :blush:

Ich dachte mir das so:
die Sendefunktion nimmt ein Array entgegen. Dieses Array ist jedoch je nach Variante unterschiedlich lang also baue ich mir bei den Präprozessordirektiven auch direkt den jeweiligen struct zusammen und gib ihn an die Sendefunktion weiter

memcpy(tx_buf, &myPayload, sizeof(myPayload) );

Muss das aber noch probieren...

Das kann ja alles sein...
Erklärt aber nicht warum das Wort struct da in der genannten Zeile stehen soll.

Weil es eben keine Funktionen sind!
Auch wenn sie (bei dir) so aussehen.

Es erleichtert das Lesen des Codes. Daß es für den Compiler auch einfacher geht ist für mich kein Argument für Verkürzungen.

Das war auch nicht mein Argument.
Es macht einfach keiner so.
Von daher trägt das eher zur Verwirrung bei.

Übrigens:

struct Test
{
  int gibWas(){ return 42; }
};



class Test test;
// struct Test test;
// Test test;


void setup() 
{
  Serial.begin(9600);
  Serial.println(test.gibWas());
  Serial.println((class Test){}.gibWas());
}

void loop() {}