Binärdaten unbestimmter Größe einlesen



  • Hallo,

    ich hab im Internet ein Charset einer 3D-Font gefunden und wollte diese in einem C-Programm nutzen. Der Autor des Charsets hat ein in C++ geschriebenes Beispielprogramm veröffentlicht, das zeigt wie man die Font laden und nutzen kann.
    Ich hänge gerade bei der Portierung das Lade-Algorithmus:

    void t3dInit()
    {
        if (font == NULL) {
            ifstream input;
            input.open("charset", istream::binary);
            font = new T3DFont(input);
            input.close();
        }
    }
    

    Wie gehe ich am besten vor um die einzelnen Daten einzulesen und diese dann einer Struktur hinzuzufügen?

    Ach ja, der Code und das Charset stammen von hier.



  • hi!
    diese zeile font = new T3DFont(input);
    ruft den konstruktor auf. du brauchst also "nur" den inhalt des konstruktors nach c zu portieren.
    wieso willst du das unbedingt in c haben?



  • Hm, ich hab mir das jetzt nochmal angeguckt und jetzt ist mir ein Licht aufgegangen. 🙂 Hab irgendwie gedacht, dass die Methode open von ifstream die Daten gleich einliest. Hätte mir aber eigentlich klar sein sollen, dass das unlogisch ist. Im ctor steht eigentlich alles was ich wissen muss.

    Ich guck mir das nochmal an. Falls es Probleme gibt melde ich mich nochmal.

    Hab keine Lust C++ zu lernen weshalb ich das in C haben möchte (und kommt mir jetzt keiner mit Aufwand und so nem Zeugs). Zumal C mehr meine eigentliche Interessen, die Hardwarenahe Programmierung, abdeckt. Hat hir zwar nichts mit Hardwarprogrammierung zu tun, aber warum eine neue Sprache lernen, wenn es Eine, die ich schon kann, auch tut?



  • klar, open gl kannst du auch mit c nutzen. dafür findest du bestimmt auch ne menge beispiele in c.



  • Ich hab jetzt endlich Zeit gefunden das Programm vollständig in C nachzubauen. Bekomme beim Ausführen allerdings einen Segmentation fault (Sf), den ich nicht nachvollziehen kann.

    Die Vorlage in C++:

    T3DFont(ifstream &input)
    {
        char buffer[8];
        input.read(buffer, 8);
        if (input.fail()) {
            throw T3DLoadException("Invalid font file");
        }
    
        const char header[9] = "VTR\0FNT\0";
        for (int i = 0; i < 8; i++) {
            if (buffer[i] != header[i]) {
                throw T3DLoadException("Invalid font file");
            }
        }
    
        input.read(buffer, 5);
        spaceWidth = toFloat(buffer);
    
        // ...
    }
    

    Mein Code:

    void Text3D_init(Text3D *text)
    {
        FILE *f = NULL;
        sloop loop, loop2;
        char buffer[8];
        const char header[9] = "VTR\0FNT\0";
    
        f = Text3D_openFile("data/charset");
        Text3D_readFile(f, buffer, 8);
        for (loop = 0; loop < 8; ++loop) {
            if (buffer[loop] != header[loop]) {
                fprintf(stderr, "Invalid font file\n");
                return;
            }
        }
    
        Text3D_readFile(f, buffer, 5);
        text->spaceWidth = toFloat(buffer);
    
        // ...
    }
    
    void Text3D_readFile(FILE *f, string buffer, int size)
    {
        fread(buffer, sizeof(buffer), size, f);
    }
    

    Der Sf kommt in meinem Code immer in Zeile 17. Das Lesen in Zeile 9 funktioniert aber ohne Probleme, was die folgende Schleife zeigt, da sie ohne Fehlermeldung durchläuft.
    Debugger-Output:

    #1  0x0000000000403d92 in Text3D_readFile (
        f=0x2924857f2a467fff, buffer=0x7fff26606030 "VTR", size=5)
        at text3d.c:258
    

    Kann mir da jemand weiterhelfen und mir erklären wie dieser Sf zustande kommt?



  • falls es noch ums einlesen von dateien unbestimmter grösse geht, hier was aus meiner snippet-sammlung:

    #include <stdio.h>
    #include <stdlib.h>
    
    /*
        Reads file into memory.
        IN: file name and pointer to variable that receives file size.
        OUT: address of file data.
    */
    char *readfile (char *filename, size_t *filesize)
    {
        FILE *fp;
        char *mem = 0;
        size_t memsize = 256;
    
        fp = fopen (filename, "rb");
        if (fp == 0)
            return 0;
    
        *filesize = 0;
        for (;;)
        {
            size_t read;
            char *tmp;
            size_t how_much = memsize - *filesize;
    
            tmp = realloc (mem, memsize);
            if (tmp == 0)
            {
                free (mem);
                fclose (fp);
                return 0;
            }
            mem = tmp;
    
            read = fread (mem + *filesize, 1, how_much, fp);
            *filesize += read;
            if (read < how_much)
                break;
    
            memsize *= 2;
        }
        fclose (fp);
        return mem;
    }
    
    // Test
    void main (void)
    {
        size_t size;
        size_t s;
        char *mem = readfile ("c:\\test.dat", &size);
    
        printf ("file size: %d\n", size);
    
        for (s=0; s<size; s++)
        {
            putchar (mem[s]);
        }
    
        free (mem);
    }
    

    ^^ähnliche findeste aber auch zig mal im internet.
    🙂



  • beim querlesen ist mir in zeile 23 aufgefallen: es wird ein string objekt übergeben.
    das schmeckt der funktion fread nicht so gut.
    mfg



  • es wird ein string objekt übergeben.

    Was ist denn das?



  • µngbd schrieb:

    es wird ein string objekt übergeben.

    Was ist denn das?

    ich nehme an es ist ein typedef für irgendeine struktur. kann man hier nicht sehen, da der code wohl ziemlich gekürzt wurde.
    🙂



  • µngbd schrieb:

    es wird ein string objekt übergeben.

    Was ist denn das?

    mmmmmmmmmh schmeckt lecker mutti! einfach mal probieren.



  • ;fricky schrieb:

    falls es noch ums einlesen von dateien unbestimmter grösse geht, hier was aus meiner snippet-sammlung

    Danke für den Code. Das Problem ist aber mittlerweile mehr, dass die Daten in einem bestimmten Format vorliegen müssen und nicht nur, dass sie unbestimmten Länge sind. Aber das hab ich glaube ich vorerst gelöst, da ich einfach den Code des Autor in C nachgebaut hab.

    ;fricky schrieb:

    µngbd schrieb:

    es wird ein string objekt übergeben.

    Was ist denn das?

    ich nehme an es ist ein typedef für irgendeine struktur. kann man hier nicht sehen, da der code wohl ziemlich gekürzt wurde.
    🙂

    string ist ein typedef auf einen Pointer auf einen char. Ich hab leider nicht genau gewusst welcher Code hier wichtig ist und welcher nicht. Der Code funktioniert beim ersten Mal ja, nur beim zweiten Mal eben nicht...

    Kleiner Nebengedanke. Woher weiß die fread-Funktion von C eigentlich von wo aus sie im Dokument lesen soll. Fängt die von vorne an und merkt sich dann was schon gelesen wurde und macht da dann weiter, oder muss ich das selber festlegen? Ich kümmere mich darum bisher nämlich nicht, der Autor des C++-Codes tut dies aber auch nicht.



  • Antoras schrieb:

    Kleiner Nebengedanke. Woher weiß die fread-Funktion von C eigentlich von wo aus sie im Dokument lesen soll. Fängt die von vorne an und merkt sich dann was schon gelesen wurde und macht da dann weiter, oder muss ich das selber festlegen?

    das merkt sich fread in der FILE-struct, die es dir bei fopen gibt.
    mit 'fseek' kannste den filepointer selber hin und herschieben.
    🙂



  • string ist ein typedef auf einen Pointer auf einen char. Ich hab leider nicht genau gewusst welcher Code hier wichtig ist und welcher nicht. Der Code funktioniert beim ersten Mal ja, nur beim zweiten Mal eben nicht...
    

    besser das nicht machen, sonst kann man den code nicht in c++ benutzern.!!



  • sorry wegn meiner fahrgelässigen formattierung, wollt törlich so machen:

    string ist ein typedef auf einen Pointer auf einen char. Ich hab leider nicht genau gewusst welcher Code hier wichtig ist und welcher nicht. Der Code funktioniert beim ersten Mal ja, nur beim zweiten Mal eben nicht...

    besser das nicht machen, sonst kann man den code nicht in c++ benutzern tun!!
    mfg



  • besser0r schrieb:

    besser das nicht machen, sonst kann man den code nicht in c++ benutzern.!!

    ^^geht doch, musste nur in c++ das #include<string.h> weglassen.
    🙂



  • noch besser0r schrieb:

    besser das nicht machen, sonst kann man den code nicht in c++ benutzern tun!!
    mfg

    Vielleicht will ich ja gar nicht, dass der Code von C++ benutzt wird. 😉
    Ehrlich gesagt hab ich daran noch gar nicht gedacht. Werde mir angewöhnen für eine Zeichenkette was anderes zu benutzen, vielleicht cstring oder so. Danke für den Hinweis!

    ;fricky schrieb:

    das merkt sich fread in der FILE-struct, die es dir bei fopen gibt.
    mit 'fseek' kannste den filepointer selber hin und herschieben.

    Ok, gut zu wissen.

    Ich bin jetzt auch bei meinem Hauptproblem weitergekommen. Hab in der Funktion Text3D_readFile einfach

    fread(buffer, sizeof(buffer), size, f);
    

    in

    fread(buffer, sizeof(char), size, f);
    

    umgeändert. Anders wäre es auch Blödsinn.

    Allerdings bekomme ich jetzt nur hässliche Grafikfetzen angezeigt. Aber den Fehler dürfte ich noch finden. Hab höchstwahrscheinlich nur was falsch portiert...



  • Antoras schrieb:

    Vielleicht will ich ja gar nicht, dass der Code von C++ benutzt wird.

    das sollteste auch garnicht erst in erwägung ziehen. würdest du's tun, dann käme völlig grausames C dabei raus.

    Antoras schrieb:

    fread(buffer, sizeof(char), size, f)

    für 'sizeof(char)' kannste auch immer 1 hinschreiben.
    🙂



  • ;fricky schrieb:

    das sollteste auch garnicht erst in erwägung ziehen. würdest du's tun, dann käme völlig grausames C dabei raus.

    Wenn ich das mache, dann nur um eine C-Library mit C++ ansprechen zu können. Mehr auch nicht.

    ;fricky schrieb:

    für 'sizeof(char)' kannste auch immer 1 hinschreiben.

    Hmm, stimmt. 🙂



  • ;fricky schrieb:

    das sollteste auch garnicht erst in erwägung ziehen. würdest du's tun, dann käme völlig grausames C dabei raus.

    Wie kommst du denn auf das schmale Brett 😕
    Man kann 1A sauber ANSI C Programmieren und in C++ Code einbinden.



  • besser0r schrieb:

    ;fricky schrieb:

    das sollteste auch garnicht erst in erwägung ziehen. würdest du's tun, dann käme völlig grausames C dabei raus.

    Wie kommst du denn auf das schmale Brett

    deswegen z.b.

    int* new = malloc (100*sizeof(int));  // gleich zwei dinge die c++ nicht will
    

    und dieses gefummel mit #ifdef __cplusplus ist auch recht blöd.
    auch weil c++ allgemein immer mehr an bedeutung verliert, braucht man's eigentlich nicht mehr zu beachten.
    🙂


Log in to reply