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 muss

    Fü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 char

    welches 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 char

    Ja, 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
    Geri

    Doch 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


Anmelden zum Antworten