Forum: PC-Programmierung Struktur mit Zeigern anlegen


von StefL_ (Gast)


Lesenswert?

Hi, will ne Struktur mit Zeigern in C initialisieren.
Kann mal jemand kurz drüber schauen ob da so richtig geht.
1
typedef struct{
2
  PNIO_UINT32 dwHandle;
3
  PNIO_UINT8 NumOfIODevives;
4
  PNIO_UINT8 MaxLen;
5
  volatile PNIO_MODE_TYPE currentMode;
6
  volatile PNIO_IOXS localState;
7
  
8
  volatile PNIO_IOXS* deviceInputState;
9
10
  PNIO_ADDR* deviceInputAddress;
11
  PNIO_UINT32* deviceInputLength;
12
  PNIO_UINT8** deviceInputData;
13
14
  volatile PNIO_IOXS* deviceOutputState;
15
16
  PNIO_ADDR* deviceOutputAddress;
17
  PNIO_UINT32* deviceOutputLength;
18
  PNIO_UINT8** deviceOutputData; 
19
}PNIO_init;
1
_declspec(dllexport)PNIO_init* setUpDevice(PNIO_UINT8 NumberOfDevices, PNIO_UINT8 MaxLen)//, PNIO_init* PNIO_init_struct)
2
{  
3
  PNIO_init PNIO_init_struct;
4
  PNIO_init_struct.NumOfIODevives = NumberOfDevices;
5
  PNIO_init_struct.MaxLen = MaxLen;
6
  PNIO_init_struct.currentMode = g_currentMode;
7
  PNIO_init_struct.localState = PNIO_S_GOOD;
8
  
9
  PNIO_init_struct.deviceInputState = (PNIO_IOXS*)malloc( NumberOfDevices * sizeof( PNIO_IOXS ) );
10
  PNIO_init_struct.deviceInputState[NumberOfDevices];
11
  PNIO_init_struct.deviceInputAddress = (PNIO_ADDR*)malloc( NumberOfDevices * sizeof( PNIO_ADDR ) );
12
  PNIO_init_struct.deviceInputAddress[NumberOfDevices];
13
  PNIO_init_struct.deviceInputLength = (PNIO_UINT32*)malloc( NumberOfDevices * sizeof( PNIO_UINT32 ) );
14
  PNIO_init_struct.deviceInputLength[NumberOfDevices];
15
  PNIO_init_struct.deviceInputData = (PNIO_UINT8**)malloc( NumberOfDevices * sizeof( PNIO_UINT8 ) * MaxLen * sizeof( PNIO_UINT8 ) );
16
  PNIO_init_struct.deviceInputData[NumberOfDevices][MaxLen];
17
18
  PNIO_init_struct.deviceOutputState = (PNIO_IOXS*)malloc( NumberOfDevices * sizeof( PNIO_IOXS ) );
19
  PNIO_init_struct.deviceOutputState[NumberOfDevices];
20
  PNIO_init_struct.deviceOutputAddress = (PNIO_ADDR*)malloc( NumberOfDevices * sizeof( PNIO_ADDR ) );
21
  PNIO_init_struct.deviceOutputAddress[NumberOfDevices];
22
  PNIO_init_struct.deviceOutputLength = (PNIO_UINT32*)malloc( NumberOfDevices * sizeof( PNIO_UINT32 ) );
23
  PNIO_init_struct.deviceOutputLength[NumberOfDevices];
24
  PNIO_init_struct.deviceOutputData = (PNIO_UINT8**)malloc( NumberOfDevices * sizeof( PNIO_UINT8 ) * MaxLen * sizeof( PNIO_UINT8 ) );
25
  PNIO_init_struct.deviceOutputData[NumberOfDevices][MaxLen];
26
27
.......................................
28
.......................................
29
30
  return &PNIO_init_struct;
31
}

Oder kann ich mir das Speicherresrvieren mit malloc auch sparen.

Kann man aus einer dll eine Adresse einer Variable an C# übergeben und 
vor allem, funktioniert das dann auch ;-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du legst eine Instanz der Struktur als lokale Variable an, d.h. auf 
dem Stack, und gibst einen Pointer auf diese Variable zurück:

StefL_ schrieb:
> _declspec(dllexport)PNIO_init* setUpDevice(PNIO_UINT8 NumberOfDevices, 
PNIO_UINT8 MaxLen)//, PNIO_init* PNIO_init_struct)
> {
>   PNIO_init PNIO_init_struct;
>
>   return &PNIO_init_struct;
> }

Sobald aber die Funktion zurückkehrt, ist der von ihr auf dem Stack 
belegte Speicher freigegeben ...

Das geht in die Hose.

von StefL_ (Gast)


Lesenswert?

Ok, danke für die schnelle Antwort.
wie kann ich es dann machen?
1
_declspec(dllexport)PNIO_init* setUpDevice(PNIO_UINT8 NumberOfDevices, PNIO_UINT8 MaxLen)
2
{
3
  PNIO_init* PNIO_init_struct;
4
  PNIO_init_struct->NumOfIODevives = NumberOfDevices;
5
.
6
.
7
.
8
  return PNIO_init_struct;

oder
1
_declspec(dllexport)void setUpDevice(PNIO_init* PNIO_init_struct, PNIO_UINT8 NumberOfDevices, PNIO_UINT8 MaxLen)
2
{
3
  PNIO_init_struct->NumOfIODevives = NumberOfDevices;
4
.
5
.
6
.
muss bei dieser Variante die Größe der Struktur nicht beim Aufruf der 
Funktion schon bekannt sein!?
wie würdet ihr das machen?

von Markus V. (valvestino)


Lesenswert?

Es stellt sich mir die Frage, wieso Du in C Speicher allokierst und 
diesen dann in C# verwenden willst. So wie ich das Code-Stück oben 
überblicke passiert nichts weiter als Speicher zu allokieren (was, wie 
Rufus bereits geschireben hat, nicht korrekt umgesetzt ist).

Du kannst diesen Speicher so nicht direkt in C# verwenden. Du mußt mit 
Hilfe der Marshalling-Funktionen des .net-PInvoke entsprechende 
Datenstrukturen in C# füllen. Solange Du keine weitere Funktionalität in 
der C-Funktion hast, ist das reichlich sinnlos.

Gruß
Markus

von StefL_ (Gast)


Lesenswert?

In der Funktion wird die Struktur noch mit Daten aufgefüllt. Ist nicht 
so sinnlos ;-).
Problem ist folgendes, ich habe weitere Funktionen in der C-dll die die 
gefüllte Struktur brauchen. Wollte das jetzt so machen:
in einer Funktion wird die Struktur gefüllt (siehe oben)
die Adresse der Struktur wird an C# geliefert
in C# werden weitere Funktionen der dll aufgerufen, denen übergebe ich 
dann jeweils wieder die Adresse der Struktur.
Wollte das in C# mit einem void Zeiger erledigen.

Ist das so möglich?
Bin eigentlich in der C-Welt zu Hause. Erste Versuche mit C# :-)...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

StefL_ schrieb:
> Ok, danke für die schnelle Antwort.
> wie kann ich es dann machen?
>
1
> _declspec(dllexport)PNIO_init* setUpDevice(PNIO_UINT8 NumberOfDevices,
2
> PNIO_UINT8 MaxLen)
3
> {
4
>   PNIO_init* PNIO_init_struct;
5
>   PNIO_init_struct->NumOfIODevives = NumberOfDevices;
6
> .
7
> .
8
> .
9
>   return PNIO_init_struct;
10
>

So gar nicht, wo ist der Speicher, auf den der Pointer PNIO_init_struct 
zeigt?


> oder
>
>
1
> _declspec(dllexport)void setUpDevice(PNIO_init* PNIO_init_struct,
2
> PNIO_UINT8 NumberOfDevices, PNIO_UINT8 MaxLen)
3
> {
4
>   PNIO_init_struct->NumOfIODevives = NumberOfDevices;
5
> .
6
> .
7
> .
8
>

Ja, genau so.

> muss bei dieser Variante die Größe der Struktur nicht beim Aufruf der
> Funktion schon bekannt sein!?

Das ist er doch.

von Arc N. (arc)


Lesenswert?

StefL_ schrieb:
> In der Funktion wird die Struktur noch mit Daten aufgefüllt. Ist nicht
> so sinnlos ;-).
> Problem ist folgendes, ich habe weitere Funktionen in der C-dll die die
> gefüllte Struktur brauchen. Wollte das jetzt so machen:
> in einer Funktion wird die Struktur gefüllt (siehe oben)
> die Adresse der Struktur wird an C# geliefert
> in C# werden weitere Funktionen der dll aufgerufen, denen übergebe ich
> dann jeweils wieder die Adresse der Struktur.
> Wollte das in C# mit einem void Zeiger erledigen.
>
> Ist das so möglich?
> Bin eigentlich in der C-Welt zu Hause. Erste Versuche mit C# :-)...

PNIO klingt nach Profinet...dann gibt's das je nach Anwendungszweck auch 
fertig...

Ansonsten für den Anfang:
http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
http://msdn.microsoft.com/en-us/magazine/cc163910.aspx
http://msdn.microsoft.com/en-us/library/sd10k43k.aspx

von StefL_ (Gast)


Lesenswert?

Danke für die Hilfe...

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.