Compilierung in Visual C++ .net mit 2 Byte-Integer-Werte, 4 Byte-long-Werte
-
Hallo zusammen
Ich arbeite mit VC2003 habe ein .net-programm geschrieben, in dem auch c-Source-Bibliotheken eingebunden sind, bei denen ein Long-Wert aus 4 Byte, ein int aus 2 etc. (nach der "alten" Konvention" besteht (unmanaged code).
Kann man dem Compiler irgendwie mitteilen z.B. indem man an bestimmte library-Files der Bibliotheken Compiler-Schalter setzt?
Schön wäre, wenn man an den Bibliotheken nicht viel ändern mussFür Eure Tipps wäre ich sehr dankbar
Beste Grüsse
Geri
-
Wo steht denn, das int 2 Bytes sind oder waren? Der ISO-C++-Standard definiert das nicht. Er sagt nur, das int mind. so groß sein soll wie short, kann aber größer sein. Und int ist bei MS 32bit- und 64bit-Compilern immer 4 byte groß. Und da long auch nur mind. so groß sein muß wie int, ist long bei MS auch 4 byte groß.
Umschalten wirst du das nicht können, da es einfach so ist. Wenn du 2 bytes benutzen willst, mußt du short benutzen.
-
Hallo Artchi
Vielen Dank für Deine Info. Du hast schon recht, dass es nicht so definiert ist. Wie du sagst, der C-Compiler in Visual C++ reserviert für einen Integer-Wert 4 Byte.
Das Problem ist, dass ich eine Struktur mit verschiedenenen einfachen Typen habe und damit einen Puffer fülle. Anschliessend wird er mit Hilfe von Marshalling ein .net kompatibler Puffer erstellt und dieser über Windsock versendet.
System::Byte buffer __gc[] = new System::Byte[256];
IntPtr ptr(UsbOutBuf);
Marshal::Copy( ptr, buffer, 0, Usbgen_tx_len );Auf der anderen Seite arbeitet ein Programm welches den Puffer empfängt und in die gleiche Struktur liest. Das Problem ist dann allerdings, dass die Ausrichtung nicht mehr stimmt.
Ich denke, eine Möglichkeit besteht darin, ein h-File mit einer Typendefinition für die Bibliothek zu erstellen, wie z.B.
#define UINT16 unsigned int
#define UINT32 unsigned long
#define BYTE unsigned char
#define INT16 int
#define INT32 long
#define INT8 char
#define UINT8 unsigned charwelches dann ensprechend der verwendeten Plattform angepasst werden kann.
Jedenfalls vielen Dank und freundliche Grüsse
Geri
PS: Das Programm läuft eigentlich auf einem Mikrocontroller. Dort werden Integer-Werte bei vielen Compiler noch mit 2 Byte (wie oft auch früher in DOS) definiert.
-
Ach ja, es sollte eher heissen:
typedef UINT16 unsigned int;
anstatt#define UINT16 unsinged int
-
Geri schrieb:
Ich denke, eine Möglichkeit besteht darin, ein h-File mit einer Typendefinition für die Bibliothek zu erstellen, wie z.B.
#define UINT16 unsigned int
#define UINT32 unsigned long
#define BYTE unsigned char
#define INT16 int
#define INT32 long
#define INT8 char
#define UINT8 unsigned charJa, das wäre ein Ansatz - allerdings solltest du (wie Artchi schon sagte) diese Zuordnungen an den verwendeten Compiler anpassen - und auf deinem VS wäre INT16 = short zu verwenden.
(btw definiert Visual Studio die INTx und UINTx Typen schon selber (als char (8), short (16), int (32) bzw. __int64 (64)))
PS@typedef: Dort hast du die Reihenfolge falsch herum:
typedef unsigned short UINT16;
-
Hallo CStoll
Vielen Dank, hast recht, habe ich falsch hingeschrieben. Nun habe ich die Lib entsprechend geändert.
Nun stehe ich aber vor einem neuen Problem.Wieso liefert mir sizof(ControllerInfo) 40 Byte?
typedef struct { UI16 CMD; UI16 Feed; UI16 SpindleSpeed; unsigned char ProcessingState; unsigned char ProcessingState2; UI16 CurrentProgramNo; unsigned char OutCtrlState; unsigned char LimitSwitchState; unsigned char ApplicationTimeoutFlag; UI16 BufCount; VectorType M0; unsigned char CurrentTool; UI16 FeedFactor; UI16 SpeedFactor; }ControllerInfo; typedef unsigned short UI16; typedef unsigned int UI32; typedef short I16; typedef int I32; typedef struct { I32 x; I32 y; I32 z; I32 w; }VectorType;
Ich habe nachgeprüft: I32,UI32 belegt 4 Byte, I16;UI16 2 Byte
Nach meiner Rechnung ergeben sich daraus nur 36 Byte
Das kuriose ist auch, dass VC die Variable M0.x an die Position 15 in einen Byte-Puffer schreibt, wenn mam memcpy verwendet.
Habe ich das etwa etwas falsch verstanden?
ControllerInfo Info;
unsigned char buf[50];memcpy(buf, &Info, sizeof(Info));
Vielen Dank falls mir hier einer weiter helfen kann und will
Geri
-
Liegt am Alignment. Dein Compiler hat nen 4 Byte Alignment eingestellt wenn er dir 40 als Göße rausgibt. So ists im Speicher drin.
typedef struct { UI16 CMD; // Byte 0+1 UI16 Feed; // Byte 2+3 // Die ersten 4 Byte voll UI16 SpindleSpeed; // Byte 4+5 unsigned char ProcessingState; // Byte 6 unsigned char ProcessingState2; // Byte 7 // Wieder 4 Byte voll UI16 CurrentProgramNo; // Byte 8+9 unsigned char OutCtrlState; // Byte 10 unsigned char LimitSwitchState; // Byte 11 // Und schon wieder 4 Byte unsigned char ApplicationTimeoutFlag; // Byte 12 UI16 BufCount; // Byte 13+14 // leeres Byte 15 //wieder 4 Byte voll VectorType M0; // Bytes 16-31 - 4*4 Byte unsigned char CurrentTool; // Byte 32 UI16 FeedFactor; // Byte 33+34 // leeres Byte 35 // wieder 4 Byte voll UI16 SpeedFactor; // Byte 36+37 // 38+39 sind wieder leer // et voilá 40 Bytes zusammengesammelt ;) }ControllerInfo;
Du hast nen 32 Bit Prozessor oder? Die Register haben dann ne Breite von 4 Byte und da ist es viel effektiver immer auch die 4 Byte auszunuzen, als wenn er doppelt kopieren muss weil eine Variable aufgeteilt wird.
-
Hall Talla
Vielen Dank für Deine Rückmeldung. Genau so wie du aufgezeigt hast, sieht es aus. Du hast recht.
Wie kann ich aber bitte den Compiler dazu zwingen eine bestimmte Struktur nicht auszrichtn. z.B.
typedef struct { char Zahl1; int Zahl2; unsigned int Zahl3; }Daten;
sizeof(Daten) sollte also 9 Byte liefern..
Freundliche Grüsse und vielen Dank
Geri
-
Hallo zusammen
Zu Eurer Info: Ich habe nun einen Weg gefunden dem VC-Compiler mitzuteilen eine Struktur nicht im Speicher auszurichten.
Man muss dazu das pack-Pragma verwenden
#pragma pack(1) // align to 1 byte typedef struct { char Zahl1; int Zahl2; unsigned int Zahl3; }Daten; #pragma pack() // mit dem Alignment fortfahren, das in den Compiler optionen eingestellt ist
In der Hoffnung, dass es einigen weiter hilft,
beste Grüsse
Geri
-
Werd ich wahrscheinlich nie brauchen, aber trotzdem gut zu wissen. Danke!
-
Geri schrieb:
Hallo zusammen
Zu Eurer Info: Ich habe nun einen Weg gefunden dem VC-Compiler mitzuteilen eine Struktur nicht im Speicher auszurichten.
Man muss dazu das pack-Pragma verwenden
#pragma pack(1) // align to 1 byte typedef struct { char Zahl1; int Zahl2; unsigned int Zahl3; }Daten; #pragma pack() // mit dem Alignment fortfahren, das in den Compiler optionen eingestellt ist
In der Hoffnung, dass es einigen weiter hilft,
beste Grüsse
GeriDoch doch, die Struktur wird auch ausgerichtet
Aber halt an 1 Byte Grenzen, was im Endeffekt dann einfach nen sequenzielles anordnen ist. Das gleiche könntest du global auch als Compilerschalter einstellen.
Problem an den Pragmas ist, das die Compilerabhängig sind, andere Compiler verstehen dieses Pragma in der Form nicht und man müsste wieder umständlich erst den Compiler Prüfen und mit #ifdefs arbeiten