struct pointer von Class zu Class

Moin....

In Class A habe ich ein Struct. Den Zeiger auf dieses Struct möchte ich Class B zur Verfügung stellen, damitt Class B in der Lage ist die Daten auf die der Zeiger zeigt zu verändern.

Geht das Überhaupt?

Was habe ich bisher gemacht:

Ich habe in einem eigenen Header "Data.h" ein Struckt definiert:

  typedef struct CFG{
    char webUser[40];
    char webPassword[40];
    char apName[40];
    char apPassword[40];
    char wifiSSID[40];
    char wifiPSK[40];
    char wifiIP[20];
    char mqttServer[20];
    char mqttPort[6];
    char mqttDeviceName[20];
  };

Dieses Struct nutze ich in Class A:
A.h

private:
CFG cfg;

um den Zeiger von cfg an die ClassB zu übergeben:
A.cpp

  B.Set_cfgPointer(&cfg);

B.h

public
  CFG *cfg;
  void Set_cfgPointer(CFG *p);

und anzulegen und zuzuweisen:
B.cpp

B::B(){	

  CFG *cfg = new CFG(); 
}


void ESP8266_Basic_webServer::Set_cfgPointer(CFG *p){
  Serial.print("setConfigPointer");
  
  cfg = p;
}

Das läuft zumindest durch.....

Wie komme ich denn jetzt an die Felder von *cfg ran?

Folgendes habe ich probiert:

  strcpy(*cfg->webUser, "Hello World!!!!!");
  strcpy(*cfg.webUser, "Hello World!!!!!");
  *cfg->webUser = "Hello World!!!!!";
  *cfg.webUser = "Hello World!!!!!";

leider ohne Erfolg...... meine Grenze ist schon wieder erreicht.... ::slight_smile:

C:\Users\Pfanne\Documents\Arduino\libraries\ESP8266_Basic\ESP8266_Basic_webServer.cpp: In member function 'void ESP8266_Basic_webServer::start()':

C:\Users\Pfanne\Documents\Arduino\libraries\ESP8266_Basic\ESP8266_Basic_webServer.cpp:28:43: error: invalid conversion from 'char' to 'char*' [-fpermissive]

strcpy(*cfg->webUser, "Hello World!!!!!");

^

In file included from c:\users\pfanne\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\stdlib.h:11:0,

from C:\Users\Pfanne\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.1.0-rc2\cores\esp8266/Arduino.h:27,

from C:\Users\Pfanne\Documents\Arduino\libraries\ESP8266_Basic/ESP8266_Basic_webServer.h:1,

from C:\Users\Pfanne\Documents\Arduino\libraries\ESP8266_Basic\ESP8266_Basic_webServer.cpp:1:

c:\users\pfanne\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\string.h:30:8: error: initializing argument 1 of 'char* strcpy(char*, const char*)' [-fpermissive]

char *_EXFUN(strcpy,(char *, const char *));

^

C:\Users\Pfanne\Documents\Arduino\libraries\ESP8266_Basic\ESP8266_Basic_webServer.cpp:29:15: error: request for member 'webUser' in '((ESP8266_Basic_webServer*)this)->ESP8266_Basic_webServer::cfg', which is of pointer type 'CFG*' (maybe you meant to use '->' ?)

strcpy(*cfg.webUser, "Hello World!!!!!");

^

C:\Users\Pfanne\Documents\Arduino\libraries\ESP8266_Basic\ESP8266_Basic_webServer.cpp:30:17: error: invalid conversion from 'const char*' to 'char' [-fpermissive]

*cfg->webUser = "Hello World!!!!!";

^

C:\Users\Pfanne\Documents\Arduino\libraries\ESP8266_Basic\ESP8266_Basic_webServer.cpp:31:8: error: request for member 'webUser' in '((ESP8266_Basic_webServer*)this)->ESP8266_Basic_webServer::cfg', which is of pointer type 'CFG*' (maybe you meant to use '->' ?)

*cfg.webUser = "Hello World!!!!!";

^

exit status 1
Fehler beim Kompilieren.

Die Frage hättest du auch allgemeiner stellen können. Das hat mit Klassen überhaupt nichts tun.

Der -> Operator ist doch gerade dazu da dass man das nicht extra per * dereferenzieren muss!

strcpy(cfg->webUser, "Hello World");

Und gut ist

"cfg->" ist eine Kurzschreibweise für "(*cfg)." , d.h. Dereferenzierung und Zugriff in einem Schritt. Die Klammern sind wichtig da . vor * kommt:
http://en.cppreference.com/w/cpp/language/operator_precedence
Also muss man erst * machen.

Aber verwende -> dann brauchst du das nicht

Och menno, ich fand mich bis dahin echt gut....

strcpy(cfg->webUser, "Hello World!!!!!");

läuft durch.....!
Führt jedoch bei der Ausführung zum Reset auf meinem ESP8266

Exception (29):
epc1=0x4000bf1b epc2=0x00000000 epc3=0x00000000 ex
cvaddr=0x00000000 depc=0x00000000

ctx: cont
sp: 3fff1a90 end: 3fff1c90 offset: 01a0

hast du da noch eine Idee?

Weiß nicht. Reagiert der ESP genauso allergisch auf zu viele Ausrufezeichen wie alte Arduino Mega Bootloader?

Abgesehen davon ist das falsch:

B::B()
{	
  CFG *cfg = new CFG();
}

Das erzeugt nur eine lokale Variable cfg. Das Objekt existiert aber weiter. Ergo, ein Speicherleck.

Auch wenn du das machst:

cfg = new CFG();

passt das insgesamt nicht, da du dann eine Methode hast die diesem Zeiger ein neues Objekt zuweist. Ohne das alte zu löschen!

Bei dynamischem Speicher musst du gut aufpassen was du machst

  //CFG *cfg = new CFG();

das war schon eher Verzweiflung.... :slight_smile:

hab ich raus genommen, genauso wie die !!!!, stürzt aber immer noch ab....

Debug mäßig kann ich es auf diese Zeile eingrenzen.....

 strcpy(cfg->webUser, "Hello World");

Kann ich prüfen, ob der Zeiger auf die selbe Adresse wie in Class A zeigt?

Ich Trottel, schon wieder.....

vielleicht wäre es sinnvoll, erst den Pointer zu übergeben und dann das Feld abzufragen!

void ESP8266_Basic::startConfigServer(){  
  webServer.Set_cfgPointer(&cfg);
  webServer.start();

Das war vertauscht!

Sorry....

Ja. Ich wollte gerade fragen ob du nicht versuchst einen Null-Pointer zu dereferenzieren.

Sicherheitshalber solltest du immer abfragen ob cfg != NULL oder cgf != nullptr (C++11) ist! Dann passiert sowas nicht

Kann ich prüfen, ob der Zeiger auf die selbe Adresse wie in Class A zeigt?

Die Adresse auf int casten (damit das von Serial.print() geschluckt wird). Auf dem PC würde man einen Cast auf void* machen, aber das geht hier nicht.

struct Test
{
  char str1[20];
  char str2[20];
};

void setup()
{
  Serial.begin(9600);

  Test test;

  Serial.println((int)&test, HEX);
  Serial.println((int)test.str1, HEX);
 Serial.println((int)test.str2, HEX);
}

void loop()
{
}

Liefert:

8D2
8D2
8E6

Die erste zwei sind gleich, da die Adresse des structs gleich der Adresse des ersten Elements ist. Das zweite Array steht 20 Bytes weiter hinten. 8E6 - 8D2 = 20(d)

Cool...

aber warum gehen die Felder ohne & ?

Serial.println((int)&test, HEX);
  Serial.println((int)test.str1, HEX);
 Serial.println((int)test.str2, HEX);

wird da nur durch das casten des chars auf das int der Zeiger generiert?

Weil Array Variablen zu Zeigern auf das erste Element zerfallen?

Arrays übergibst du ja auch so an Funktionen:

void func(int* array)
{
}

...

int array[10];
func(array);

Das ist das gleiche wie:

func(&array[0]);

Oh man, da muss ich aber noch eine Menge lernen.....
Aber wie immer lernt man am Besten an einem Projekt!

Wenn man dann noch so prima Unterstützung hat ist der Frustfaktor erträglich!
Danke für deine Unterstützung!