• chevron_right

      C Beispiel struct und Zeiger

      Stefan · Wednesday, 30 June, 2021 - 05:11

    Hier ein Beispiel wegen einer Frage aus dem C/C++ Gruppenchat

    #include <stdlib.h>
    #include <stdio.h>
    #include <assert.h>
    
    typedef struct {
    	int x;
    	int y;
    } C;
    
    static void _set(C* c, int x, int y);
    
    int main( int argc, char argv[]) {
    	C* c = malloc(sizeof(C));
    	_set(c, 10, 20);
    	printf("c: x=%d y=%d\n", c->x, c->y);
    	_set(c, ++(c->x), ++(c->y));
    	printf("c: x=%d y=%d\n", c->x, c->y);
    	free(c);
    	return EXIT_SUCCESS;
    
    }
    
    static void _set(C* c, int x, int y) {
    	assert(c);
    	c->x = x;
    	c->y = y;
    }
    
    • chevron_right

      C - Bits und Bytes

      Stefan · Sunday, 29 November, 2020 - 11:56 · 1 minute

    #include <stdlib.h>
    #include <stdio.h>
    #include <limits.h>
    
    // HEX: ABCD - 1010 1011 1100 1101
    
    int main( int argc, char* argv[] ) {
    
        printf("unsigned short...\n");
        unsigned short x = USHRT_MAX;
        printf("unsigned short MAX:\t%hu\n", x);
        printf("unsigned short MAX+1:\t%hu\n", x+1);
        printf("unsigned short MAX:\t0x%X\n\n", x);
    
        printf("unsigned char MAX:\t%hhu\n", UCHAR_MAX );
        printf("unsigned char MAX+1:\t%hhu\n", UCHAR_MAX+1);
        printf("unsigned char MAX:\t0x%X\n\n", UCHAR_MAX );
    
        x = 0xABCD;
    
        unsigned char h = (x>>8);
        unsigned char l = x;
    
        printf("x = 0x%X\n", x);
        printf("h = 0x%X\n", h);
        printf("l = 0x%X\n", l);
    
        printf("bh1 = %c\n", h & 0x01 ? '1' : '0');
        printf("bh2 = %c\n", h & 0x02 ? '1' : '0');
        printf("bh3 = %c\n", h & 0x04 ? '1' : '0');
        printf("bh4 = %c\n", h & 0x08 ? '1' : '0');
        printf("bh5 = %c\n", h & 0x10 ? '1' : '0');
        printf("bh6 = %c\n", h & 0x20 ? '1' : '0');
        printf("bh7 = %c\n", h & 0x40 ? '1' : '0');
        printf("bh8 = %c\n", h & 0x80 ? '1' : '0');
    
        printf("bl1 = %c\n", l & 0x01 ? '1' : '0');
        printf("bl2 = %c\n", l & 0x02 ? '1' : '0');
        printf("bl3 = %c\n", l & 0x04 ? '1' : '0');
        printf("bl4 = %c\n", l & 0x08 ? '1' : '0');
        printf("bl5 = %c\n", l & 0x10 ? '1' : '0');
        printf("bl6 = %c\n", l & 0x20 ? '1' : '0');
        printf("bl7 = %c\n", l & 0x40 ? '1' : '0');
        printf("bl8 = %c\n", l & 0x80 ? '1' : '0');
    
        return EXIT_SUCCESS;
    }
    
    • chevron_right

      XMPP XEPs ganz einfach

      Stefan · pubsub.movim.eu / xmpp-messenger · Thursday, 11 June, 2020 - 12:26 edit · 2 minutes

    Nachdem ich mich jetzt einige Zeit mit C und XMPP beschäftige, sollte man mal überlegen von den "Sandbox" Projekten mal auf etwas sinnvollere Projekte umzusteigen.

    Ich habe angefangen etwas OX zu implementieren. Dies habe ich erst in xmppc umgesetzt, dann in einem meiner eigenen Clients und jetzt will ich es in profanity implementieren. 3x die gleiche Arbeit für mehr oder weniger umsonst.

    Ich habe jetzt mit einer lib für C angefangen.

    Die Idee

    libstrophe als normale XMPP lib verwenden (eigentlich die Kommunikation mit dem Server und die Umsetzung der Grundfunktionen von XMPP). Da drauf dann eine lib (libcxmppx) für die Implementierungen der XEPs.

    Beispiel

    stanza_id_t cxmppx_ox_signcrypt_message( xmpp_stanza_t **stanza, xmpp_conn_t *conn, xmpp_adr_t xmpp_adr, char* message);
    

    In der Funktion wird die stanza für eine signcrypt erzeugt. Die Funktion übernimmt alle Aufgaben wie key-lookup / openpgp sign / openpgp crypt / base64.

    void fire_and_handle(xmpp_conn_t *const conn,stanza_id_t id, xmpp_stanza_t *stanza, cxmppx_stanza_result_cb_t callback, void *const userdata);
    

    Danach werden die stanza abgefeuert und über das callback und userdata können die Antworten verarbeitet werden.

    Eine Implementierung kann dann so aussehen:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <cxmppx.h>
    
    static char* to_adr = NULL;
    static xmpp_conn_t *conn = NULL;
    
    void handle(xmpp_stanza_t *stanza, void *const obj, void *const userdata ) {
      printf("%s %s\n", userdata, obj);
      xmpp_disconnect(conn);
    }
    
    void conn_handler(xmpp_conn_t *const conn, const xmpp_conn_event_t status,
                      const int error, xmpp_stream_error_t *const stream_error,
                      void *const userdata) {
      switch (status) {
        case XMPP_CONN_CONNECT:
          printf("Connected!\n");
          xmpp_stanza_t* message = NULL;
          stanza_id_t id = cxmppx_ox_signcrypt_message(&message, conn, to_adr, "Das ist ein Test");
    
          fire_and_handle(conn, id, message, handle, "Anfrage 1" );
    
          break;
        case XMPP_CONN_DISCONNECT:
        case XMPP_CONN_FAIL:
          xmpp_stop(xmpp_conn_get_context(conn));
          break;
      }
    
    }
    
    int main(int argc, char* argv[]) {
      xmpp_log_t *log = NULL;
      log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
      xmpp_ctx_t *ctx = xmpp_ctx_new(NULL, log);
      conn = xmpp_conn_new(ctx);
      xmpp_conn_set_jid(conn, argv[1]);
      xmpp_conn_set_pass(conn, argv[2]);
    
      to_adr = strdup(argv[3]);
    
      int e =  xmpp_connect_client(conn, NULL, 0, conn_handler, NULL);
      if(XMPP_EOK != e ) {
        printf("xmpp_connect_client failed");
      }
    
      xmpp_run(ctx);
      xmpp_conn_release(conn);
      xmpp_ctx_free(ctx);
      xmpp_shutdown();
    
      return EXIT_SUCCESS;
    }
    

    Der Code ist auf Codeberg https://codeberg.org/xmpp-messenger/libcxmppx und ein Spiegel auf gitlab https://gitlab.com/xmpp-messenger/libcxmppx

    • chevron_right

      C-Kurs im XMPP Multi User Chat

      Stefan · Monday, 25 May, 2020 - 19:12 edit · 2 minutes

    Kann man einen C-Kurs im XMPP Multi User Chat halten? Wir versuchen es einfach mal. Die Idee: Kleine Menge an Informationen, an einem Abend oder Wochenende und dann warten bis die Teilnehmer die Möglichkeit hatten dies zu lesen.

    Heute

    Das einfachste Programm in C sieht wie folgt aus. Das Programm ist noch einfacher als "Hello World". Denn hier wird nicht mal etwas ausgegeben.

    /*
     * Datei: main.c
     * Kompilieren: gcc -o hello main.c
     */
    
    #include <stdlib.h>                 // C-Präprozessor Direktive
    
    int main(int argc, char* argv) {    // main-Funktion
      return EXIT_SUCCESS;              // main-Funktion verlassen
    }
    

    Man erstellt aus dem Quellcode eine ELF-Datei (ausführbare Datei) mit dem folgenden Befehl: gcc -o hello main.c. Hier passieren 3 Schritte: Präprozessor, Compiler, Linker. Wenn alles funktioniert, kann man das Programm mit ./hello ausführen. (Was ich vergessen habe, wir sind auf einem Linux System,... aber dies setzte ich mal voraus).

    Das ist aber schon ein Fehler drin. :-)

    /*
     * Datei: main.c
     * Kompilieren: gcc -o hello main.c
     */
    
    #include <stdlib.h>                 // C-Präprozessor Direktive
    
    int main(int argc, char* argv[]) {    // main-Funktion
      return EXIT_SUCCESS;              // main-Funktion verlassen
    }
    

    Noch ein Hinweis, ich bin beruflich kein C Programmierer. D.h. alles kann ich nicht beantworten und bei einigen Sachen muss ich auch erst nachlesen. Aber vielleicht kann man es ja zusammen erarbeiten. Ich kompiliere meine Programme i.d.R. mit einigen Optionen. Auf die sollte man vielleicht später noch mal eingehen: gcc -Wno-deprecated-declarations -pedantic -std=c18 -Wno-deprecated-declarations -pedantic -std=c18 -Wunused -Werror -g -O0 -o hello main.c Vom Ablauf,... ich würde vorschlagen ich lade die Sachen hier hoch: https://codeberg.org/DebXWoody/hello-c dann kann man immer nachlesen bzw. auch mal hin und her springen. Wenn man aber C lernen will, sollte man die Sachen am besten selber mitmachen. Die main wird von einer Standard Bibliothek aufgerufen und ist somit immer der "start" des Programms. Es ist die Funktion die also vom Betriebssystem aufgerufen wird. Wenn ich mich richtig erinnere, dann gibt es hier einen Sonderfall. Das liegt an der Speicherverwaltung. Ich glaube es hat was damit zutun, dass der Speicher in dem argv liegt nicht im Prozess gehört. Das aber nur nebenbei. Das Programm beenden mit einem return Code. Wenn alles ok ist, in der Regel mit 0 (EXIT_SUCCESS). Was sich danach in der Shell mit echo $? abfragen lässt. Die Übergabeparameter "int argc, char* argv[]" der Main-Funktion sind die Argumente, die an den Prozess übergeben werden. Also ./hello --help. Das steht dann da drin. Details folgen. Die #include C-Präprozessor Anweisung zieht den Inhalt aus der Datei stdlib.h rein - was beim Präprozessor passiert. Deswegen kennt das Programm den Namen 'EXIT_SUCCESS' und weiß, dass dies 0 ist. Ohne das #include wird der compiler einen Fehler ausgeben:

    main.c: In function ‘main’:
    main.c:10:10: error: ‘EXIT_SUCCESS’ undeclared (first use in this function)
       return EXIT_SUCCESS;              // main-Funktion verlassen
              ^~~~~~~~~~~~
    main.c:10:10: note: each undeclared identifier is reported only once for each function it appears in
    

    ‎Was der Befehl gcc -Wno-deprecated-declarations -pedantic -std=c18 -Wunused -Werror -g -O0 -o hello main.c also macht. Ist dann folgendes:

    gcc -E main.c # Preprocess only; do not compile, assemble or link.
    gcc -S main.c # Compile only; do not assemble or link.
    gcc -c main.c # Compile and assemble, but do not link.
    ld -o hello main.o # Hier fehlen aber noch weitere Parameter
    

    Wird man am Anfang nicht brauchen, aber es ist sicher nicht falsch es mal gehört zu haben und eine Vorstellung zu haben was da passiert.