Forum: PC-Programmierung C: Private Struktur als Teil einer Public Struktur


von Mark M. (mom-jovi)


Lesenswert?

Ich würde gerne in einem C-Modul für einen Hardware-Treiber eine public 
Struktur deklarieren, die wiederum eine Struktur enthält, welche 
allerdings privat ist.

Geht sowas in C überhaupt?

Ich habe folgendes probiert, aber das funktioniert nicht, da die Public 
Deklaration im Header ja noch nichts von dem Private typedef weiß:
1
/**
2
 * driver.h
3
 */
4
typedef struct driver_class
5
{
6
   void attribute_1;
7
   void attrivute_2;
8
   driver_hardware_t hardware;
9
} driver_class_t;
10
11
12
/**
13
 * driver.c
14
 */
15
#include driver.h
16
17
typedef struct driver_hardware_t
18
{
19
   void* pHWModule1;
20
   void* pHWModule2;
21
}
22
23
/**
24
 * main.c
25
 */
26
#include driver.h
27
28
void main(void)
29
{
30
   driver_class_t   instance;
31
}

Die Private typedef muss nicht unbedingt eine Struktur sein, eine 
eifache Hardware-Adresse reicht evtl. auch. Aber hier nehmen wir an, 
dass der HW Treiber 2 Peripherie-Module ansprechen muss, z.B. Timer und 
ADC.

von Dr. Sommer (Gast)


Lesenswert?

1
struct myStruct {
2
public:
3
  int somePublicMember;
4
private:
5
  int somePrivateMember;
6
};
Und den "gcc" Aufruf durch "g++" ersetzen.

von Mark M. (mom-jovi)


Lesenswert?

Dr. Sommer schrieb:
>
1
struct myStruct {
2
> public:
3
>   int somePublicMember;
4
> private:
5
>   int somePrivateMember;
6
> };
> Und den "gcc" Aufruf durch "g++" ersetzen.

:-) Es geht hier aber um eine Lösung in C, da C++ nicht zum Einsatz 
kommt.

von Dr. Sommer (Gast)


Lesenswert?

Mark M. schrieb:
> :-) Es geht hier aber um eine Lösung in C, da C++ nicht zum Einsatz
> kommt.
Warum versuchen immer alle C++ in C zu emulieren? Wenn man schon in 
private,public oder gar Objekten etc. denkt, kann man auch gleich C++ 
verwenden ohne sich den Krampf in C anzutun. Und sofern deine Plattform 
nicht völlig obskur ist wird es auch einen C++ Compiler geben, wenn du 
GCC verwendest eben einfach "gcc" durch "g++" ersetzen.

von (prx) A. K. (prx)


Lesenswert?

Was nicht geht:
1
typedef struct driver_class
2
{
3
   ...
4
   driver_hardware_t hardware;
5
} driver_class_t;

Was geht:
1
typedef struct driver_class
2
{
3
   ...
4
   struct driver_hardware_s *hardware;
5
} driver_class_t;

Soll heissen: Ein Pointer auf eine unbekannte struct ist zulässig, aber 
auch nur der. Grund: Die Grösse des Pointers ist von der Definition der 
struct unabhängig.

: Bearbeitet durch User
von Tom K. (ez81)


Lesenswert?

Die von AK beschriebene Methode heißt opaque pointer oder PIMPL :
http://en.wikipedia.org/wiki/Opaque_pointer#C

von Rolf Magnus (Gast)


Lesenswert?

Alternativ geht man den Schritt zur Kapselung nicht nur halb, sondern 
gleich ganz und macht auch die struct driver_class nicht "public". 
Zugriff nur über Funktionen.

von Karl H. (kbuchegg)


Lesenswert?

Rolf Magnus schrieb:
> Alternativ geht man den Schritt zur Kapselung nicht nur halb, sondern
> gleich ganz und macht auch die struct driver_class nicht "public".
> Zugriff nur über Funktionen.

Jep.
Und um dem geneigten Verwender dann auch noch jegliche Lust zu nehmen, 
da Tricks zu versuchen, kann man das Interface dann anstelle von 
spezfischen Pointern mit void Pointern gestalten. Dann muss man selbst 
zwar an den Schnittstellen ein wenig casten, aber der Verwender müsste 
das auch exzessiv tun.
Einen void Pointer hingegen kann er speichern und beim Aufruf einer 
anderen Funktion wieder benutzen ohne auch nur je davon gehört zu haben, 
wie die dahinter stehende Struktur heißt.
Nachteil natürlich: man hebelt sich selbst jegliche Typprüfung weg.

von Rolf Magnus (Gast)


Lesenswert?

Es reicht doch, im Header nur eine Forward Declaration der Struct zu 
machen und einen Pointer darauf zu verwenden.

Karl Heinz schrieb:
> Einen void Pointer hingegen kann er speichern und beim Aufruf einer
> anderen Funktion wieder benutzen ohne auch nur je davon gehört zu haben,
> wie die dahinter stehende Struktur heißt.

Was ist denn so schlimm dran, wenn er das weiß?

von Mark M. (mom-jovi)


Lesenswert?

Rolf Magnus schrieb:
> Alternativ geht man den Schritt zur Kapselung nicht nur halb, sondern
> gleich ganz und macht auch die struct driver_class nicht "public".
> Zugriff nur über Funktionen.
Der Hardware-Treiber soll aber so modular sein, dass ich bspw. bei einem 
uC mit 8 ADC und 4 Timern jeden mit jedem kombinieren kann - 
vorausgesetzt die Hardware lässt das zu. Heute so, morgen so. ;-)
Wenn ich also die struct driver_class auch "private" mache, muss ich mir 
ein enum o. ä. definieren, und bin damit in der Anzahl Instanzen 
beschränkt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.