Wie Instanz mit fremder Lib in eigener Lib erstellen?

Hallo,

ich bin dabei eine Lib zu schreiben mit Auftrennung in .h und .cpp. Ich weiß nicht wie ich ein Objekt einer fremden Lib darin instanziere. In meiner vorherigen Header only Lib ging das ohne Probleme. Es geht um die MoToServo Lib und das erstellte Objekt servo. Falls das wichtig ist, die Lib MoToServo ist Header only.

Meine alte Header only Lib sieht so aus. Funktioniert.

class WeichenServo
{
  private:
    const byte pin;
    const byte winkelGerade;
    const byte winkelAbzweig;
    const byte servoSpeed;
    unsigned long timeEndposition;
    MoToServo servo;          // <<-- darum gehts
     
    ...
    ...
    
  public:
    WeichenServo(byte p, byte wG, byte wA, byte sp):
      pin {p},
      winkelGerade {wG},
      winkelAbzweig {wA},
      servoSpeed {sp},
      timeEndposition {0}
    {}

    void init (void) {
      ...         
    }

Die .h meiner neuen Lib sieht aktuell so aus.

#pragma once

#include <Arduino.h>
#include <utilities/MoToServo.h>

class WeichenServo
{
  private:
    const byte pin;
    const byte winkelGerade;
    const byte winkelAbzweig;
    const byte servoSpeed;
    unsigned long timeEndposition;
    
  public: 
    WeichenServo(byte p, byte wG, byte wA, byte sp);
    void init (void);
};

Die .cpp sieht so aus.

#include "WeichenServo.h"
#include <utilities/MoToServo.h>
  
WeichenServo::WeichenServo(byte p, byte wG, byte wA, byte sp): 
  pin {p},
  winkelGerade {wG},
  winkelAbzweig {wA},
  servoSpeed {sp},
  timeEndposition {0}
{}

void WeichenServo::init (void)
{
  pinMode(pin, OUTPUT);
  //servo.attach(pin);  
  //servo.setSpeed(servoSpeed);  
  //servo.write(winkelAbzweig);          
}

Das servo Objekt soll nicht nach außen sichtbar sein. Wird nur intern benötigt. Nur die Pin Nummer wird von außen übergeben. Nur wo und wie erstelle ich das servo Objekt von MotToServo? Alle Bsp. die ich finde verwenden Header only. Hilft mir nicht, hab ich schon. Ideen? Ich bekomme das nicht hin. Entweder undefinierte Referenz oder One Rule Verletzung. Ich drehe mich in Kreis. Wie wirds gemacht?

ein using vieleicht

Hallo,

ginge das bitte noch etwas ausführlicher?

nein, musst du selber etwas ergoogeln, wenn ich es genau wüsste hätte ich es geschrieben.

https://en.cppreference.com/w/cpp/language/using_declaration

Frage, warum machst du ein include auf das src und nicht

#include <MobaTools.h>
?
dann kompiliert das bei mir... auch wenn ich eine Instanz von WeichenServo anlege.

Zeige mir mal was du wo genau anlegst? Sonst reden wir aneinander vorbei. Ich kann nicht sehen was du machst.
Die kompletten MobaTools zu inkludieren machens bei mir noch nicht. Darin wird dann "auch nur" die MoToServo.h inkludiert.

libverzeichnis
Unterverzeichnis NoiascaTest
hidden.h

#pragma once

#include <Arduino.h>
//#include <utilities/MoToServo.h>


#include <MobaTools.h>

class WeichenServo
{
  private:
    const byte pin;
    const byte winkelGerade;
    const byte winkelAbzweig;
    const byte servoSpeed;
    unsigned long timeEndposition;
    
    MoToServo servo;          // <<-- darum gehts
    
   // using MoToServo;
    
  public: 
    WeichenServo(byte p, byte wG, byte wA, byte sp);
    void init (void);
};

hidden.cpp

#include "hidden.h"
#include <utilities/MoToServo.h>
  
WeichenServo::WeichenServo(byte p, byte wG, byte wA, byte sp): 
  pin {p},
  winkelGerade {wG},
  winkelAbzweig {wA},
  servoSpeed {sp},
  timeEndposition {0}
{}

void WeichenServo::init (void)
{
  pinMode(pin, OUTPUT);
  //servo.attach(pin);  
  //servo.setSpeed(servoSpeed);  
  //servo.write(winkelAbzweig);          
}

usersketch

#include "hidden.h"



WeichenServo foo(1, 2, 3, 4);

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}
1 Like

Hallo,

vielen Dank. Ich war immer nah dran gewesen was zwangsweise immer vorbei ist. Ich musste wie bei dir jetzt gesehen das

#include <MobaTools.h>

im Hauptsketch entfernen.

Was ich gleichzeitg nicht verstehe warum das stört?
One Rule sorgt doch dafür das alles nur einmal inkludiert wird, egal wie oft man das einbindet. Die Arduino.h wird doch auch zigmal inkludiert und das stört niemanden. :face_with_monocle:

Edit:
Jetzt habe ich das

#include <MobaTools.h>

wieder im Hauptsketch als Erstes eingefügt und im WeichenServo.h Headerfile rausgenommen. Sollte ja weiterhin kompilieren, weil MobaTools.h vor WeichenServo.h eingebunden wird und damit global bekannt ist. Klappt aber nicht. Wo ist dabei die Logik versteckt?

die hidden.h braucht die Mobatools, weil die ja die Servoklasse verwendet.
du musst jede Übersetzungseinheit für sich betrachten.
und so ist die hidden.h/hidden.cpp vor dem Usersketch dran.

Vermutlich total falsch erklärt, aber da wird schon noch jemand anderer kommen ^^

Hallo,

das eine .cpp separat für sich übersetzt wird und ihr alles bekannt sein muss ist mir soweit klar.
Nur das Headerfile kommt doch erst dran wenn der Hauptsketch übersetzt wird. Würde bedeuten man müßte alle Libs "versteckt" inkludieren. Was meistens nicht gemacht wird und von vielen auch nicht gewollt ist. Damit man die Abhängigkeiten sofort sieht und man nicht erst in den Libs nachschauen muss.

Ich kann jetzt auch im Hauptsketch die Arduino.h inkludieren und das macht keine Probleme.

Mich beschleicht das dumpfe Gefühl ich sitze noch auf einem kleinen Pulverfass.

Vielleicht hat jemand noch eine Erklärung dafür?

Nee, das kommt m.E. auch schon dran, wenn die Implementierung der Klasse übersetzt wird: Bei Dir #include "WeichenServo.h" und bei Werner #include "hidden.h"

Hallo,

bin da irgendwie anderer Meinung. Ich dachte noch das liegt an der Reihenfolge der Inkludierung in der .cpp. Hilft aber auch nicht.

Die .cpp wird für sich übersetzt. Die hat alles was sie benötigt. MobaTools.h und ihr eigenes Headerfile.

WeichenServo.cpp

#include <MobaTools.h>
#include "WeichenServo.h"

WeichenServo.h

#pragma once

Danach kommt der Hauptsketch dran. Hier werden laut meines Wissens alle Headerfiles der Inkludierungsreihenfolge aneinandergehängt. Das heißt wenn WeichenServo.h dran kommt ist MobaTools.h schon eingebunden und damit bekannt. Im Grunde genauso so wie beim übersetzen der .cpp.
Das Headerfile WeichenServo.h wird ja nicht einzeln übersetzt. Sondern erst im Hauptsketch mit allen sonstigen Headerfiles.

Hauptsketch

#include <MobaTools.h>  
#include <WeichenServo.h>

Stimmt nicht? Wo ist mein Denkfehler?

Irgendwie kann ich dein Problem noch nicht nachvollziehen. Wie bei noiasca kompiliert das auch bei mir:
Sketch:

#include <MobaTools.h>  //<-- eigentlich unnötig,, stört aber auch nicht
#include "WeichenServo.h"


WeichenServo foo(1, 2, 3, 4);

void setup() {
  // put your setup code here, to run once:
  foo.init();

}

void loop() {
  // put your main code here, to run repeatedly:

}

WeichenServo.h:

#pragma once

#include <Arduino.h>
#include <MobaTools.h>

class WeichenServo
{
  private:
    const byte pin;
    const byte winkelGerade;
    const byte winkelAbzweig;
    const byte servoSpeed;
    unsigned long timeEndposition;
    MoToServo servo;          // <<-- darum gehts
    
  public: 
    WeichenServo(byte p, byte wG, byte wA, byte sp);
    void init (void);
};

WeichenServo.cpp:

#include "WeichenServo.h"
  
WeichenServo::WeichenServo(byte p, byte wG, byte wA, byte sp): 
  pin {p},
  winkelGerade {wG},
  winkelAbzweig {wA},
  servoSpeed {sp},
  timeEndposition {0}
{}

void WeichenServo::init (void)
{
  pinMode(pin, OUTPUT);
  servo.attach(pin);  
  servo.setSpeed(servoSpeed);  
  servo.write(winkelAbzweig);          
}

Hallo,

diese Variante kompiliert ja auch bei mir. Es geht darum warum folgende nicht kompiliert. Ich habe mich nochmal belesen. Die Headerfiles werden genau an der Stelle eingebunden wo sie inkludiert werden. Demzufolge muss MobaTools.h vorm einbinden der WeichenServo.h in der .ino bekannt sein. Die .cpp ist außenvor bzw. ist zu dem Zeitpunkt schon übersetzt.

.ino

#include <MobaTools.h>  
#include "WeichenServo.h"

WeichenServo foo(1, 2, 3, 4);

void setup() {
  foo.init();
}

void loop() {

}

WeichenServo.h

#pragma once

class WeichenServo
{
  private:
    const byte pin;
    const byte winkelGerade;
    const byte winkelAbzweig;
    const byte servoSpeed;
    unsigned long timeEndposition;
    MoToServo servo;        
    
  public: 
    WeichenServo(byte p, byte wG, byte wA, byte sp);
    void init (void);
};

WeichenServo.cpp

#include "WeichenServo.h"
  
WeichenServo::WeichenServo(byte p, byte wG, byte wA, byte sp): 
  pin {p},
  winkelGerade {wG},
  winkelAbzweig {wA},
  servoSpeed {sp},
  timeEndposition {0}
{}

void WeichenServo::init (void)
{
  pinMode(pin, OUTPUT);
  servo.attach(pin);  
  servo.setSpeed(servoSpeed);  
  servo.write(winkelAbzweig);          
}

Die ist absolut nicht außen vor, sondern der Grund für das Problem. In der Variante bekommst Du einen Fehler beim Übersetzen der .cpp-Datei, weil MobaTools.h da nicht eingebunden wird, und dementsprechen der Compiler auch nicht weis, was er mit dem 'servo-Geraffel' anfangen soll.
Deine WeichenServo.h sollte alles mit einbinden, was sie braucht - also auch die MobaTools.

P.S. Die Arduino.h muss auch wieder rein, die wird bei dem .cpp nicht automatisch eingebunden. Funktioniert in diesem Fall zwar auch so, da die Arduino.h über die MobaTools.h inidirekt eingebunden wird. Darauf sollte man sich aber nicht verlassen dass das bei allen Libs immer so ist.

1 Like

Hallo,

okay, dass leuchtet ein. Dann sah ich gestern keine klaren Bilder mehr. :wink:
Vielen Dank.