pl: ctemplate.h

Hi, etwas OT, es geht um eine Templating Engine in c mit der ich grad die ersten Schritte tu.

Problem macht die Funktion TMPL_write("tmplfile", 0, 0, mylist, stdout, stderr); die Templatedatei wird einfach nicht gefunden, egal ob ich mit relativen oder absoluten Pfadangaben arbeite.

Da bin ich echt ratlos, vielleicht hat ja jemand eine Idee dazu. Ansonsten funktioniert das Teil ganz wunderprächtig mit Templates die auch zu HTML::Template passen.

MfG

source

  1. 
    > TMPL_write("tmplfile", 0, 0, mylist, stdout, stderr);
    
    

    Kann an der 0 liegen. Im Handbuch steht:

    Parameter filename is the name of the template file. If parameter tmplstr is non-null, then it is the template, a null terminated string.

    Dieses "null" ist, als Begriff, ziemlich dehnbar. Versuchs mal mit gar nichts zwischen den Kommas (,,) , null, "" oder ''.

    TMPL_write("tmplfile",, 0, mylist, stdout, stderr);
    TMPL_write("tmplfile", null, 0, mylist, stdout, stderr);
    TMPL_write("tmplfile", '', 0, mylist, stdout, stderr);
    TMPL_write("tmplfile", "", 0, mylist, stdout, stderr);
    
    1. Danke Dir, isn Ansatz. Ob diese Lib auch für c++ geeignet ist, wäre dann die nächste Frage.

      MfG

    2. hi fastix,

      so langsam werd ich wieder warm mit c 😉

      Eine 0 in char *string = 0 ist völlig Ok, 1. wird der Pointer initialisiert und 2. funktionieren damit die Kontrollstrukturen. D.h., ein if(string) würde immer wahr ergeben wenn string = "" (Leerstring) ist und das ist schlecht. Mit 0 initialisiert hingegen klappt das einwandfrei.

      Gleichermaßen verhält es sich mit den Rückgabewerten von Funktionen wenn das Stringspointer sein sollen char *func(){}. So gibt es ein return 0; wenn meine Funktion beim Durchlaufen einer verketteten Liste den gesuchten String nicht gefunden hat ansonsten einen Zeiger auf den String.

      Was ctemplate.c betrifft, so nehme ich zum Lesen der Templatedatei nun eine eigene Routine weil ich eine Solche ohnehin auch anderweitig brauche.

      Mein Web Framework in c -- das ist der Plan. Da werde ich mal weitermachen, bis jetzt sieht das schon ganz gut aus, d.h., das Ausliefern bestimmter Seiten per c fügt sich nahtlos in das FW ein was ansonsten in Perl geschrieben ist.. vom Tempo her genauso schnell als würde der Apache die Seite selbst ausliefern und nicht über die CGI Schnittstelle schleifen.

      MfG

      1. Moin pl,

        Eine 0 in char *string = 0 ist völlig Ok, 1. wird der Pointer initialisiert und 2. funktionieren damit die Kontrollstrukturen. D.h., ein if(string) würde immer wahr ergeben wenn string = "" (Leerstring) ist und das ist schlecht. Mit 0 initialisiert hingegen klappt das einwandfrei.

        In C gibt es auch keine Strings, sondern nur Arrays von Zeichen – und ein Array ist letztlich nur ein Pointer auf die erste Position der Elemente. Als „String“ wird ein Zeichenarray betrachtet, dessen letztes Zeichen 0 ist. Daher ist "" auch ein Zeichenarray der Länge 1, bestehend aus dem NULL-Byte und mit einer von 0 unterschiedlichen Position im Speicher. Dein Vergleich if(string) müsste daher in C heißen

        if (strlen(string)) {
            /* … */
        }
        

        Gleichermaßen verhält es sich mit den Rückgabewerten von Funktionen wenn das Stringspointer sein sollen char *func(){}. So gibt es ein return 0; wenn meine Funktion beim Durchlaufen einer verketteten Liste den gesuchten String nicht gefunden hat ansonsten einen Zeiger auf den String.

        Vorsicht:

        char* func(char *arg) {
            char intern[23];
            static char ext[42];
            char *dynamic = (char*) malloc(42);
        
            /* Führt zu undefiniertem Verhalten, weil die Variable nur im Scope der Funktion existiert:
             * return intern;
             */
        
            /* Funktioniert, erfordert aber ggf. eine Kopie des statischen Strings:
             * return ext;
             */
        
            /* Funktioniert, String muss aber nach Verwendung freigegeben werden um Memoryleaks zu vermeiden:
             * return dynamic;
             */
        
            return 0;
        }
        

        Viele Grüße
        Robert

        1. hi danke,

          Überraschungen gibt es natürlich 😉 Btw., mein gcc gibt Warnung, wenn eine Variable returned werden soll die nur im Scope der Funktion existiert.

          MfG

  2. Btw., in meiner Konfiguration lege ich Namen von Funktionen fest. Gibt es in c eine Möglichkeit, mit einem konfigurierten Namen eine gleichnamige Funktion aufzurufen? Also unmittelbar?

    Bitte mal um Hinweises.

    1. Tach!

      Btw., in meiner Konfiguration lege ich Namen von Funktionen fest. Gibt es in c eine Möglichkeit, mit einem konfigurierten Namen eine gleichnamige Funktion aufzurufen? Also unmittelbar?

      Dazu müsste C über Reflection verfügen. Da es das da nicht gibt, geht die Information zu Namen beim Compilieren verloren.

      dedlfix.

      1. Nein eval meinte ich nicht. Sondern vielmehr sowas execute('Functionsname'). Die übliche Vorgehensweise besteht darin, anhand Funktionsname zu ermitteln ob es eine solche Funktion im aktuellen Namespace gibt. Das kann sogar PHP und im Ergebnis einer solchen Prüfung bekommt man eine Referenz auf den Code den man somit ausführen kann.

        Sowas für c oder c++

        PS: Für c++ nicht die Methode sondern die Instanzerstellung anhand Namen einer Klasse.

        1. Sowas für c oder c++

          Factory Class

          1. Google Ergebnis({"search":"cpp dynamic class"}), 2. Antwort
          1. Nein was Du gefunden hast, ist es leider nicht. Aber danke totzdem.

            1. Hallo pl,

              PHP und JavaScript sind Scriptsprachen, die sich auf gewaltige Dictionaries stützen. Das kostet Zeit, bringt aber die Flexibilität dieser Sprachen.

              C ist ein Makroassembler mit großer Laufzeitbibliothek und einigem Geschick beim Hantieren mit Expressions, die zu einzeiligen Programmen beliebiger Komplexität führen können.

              D.h. wenn Du Funktionen namentlich aufrufen können willst, dann

              • müssen diese Funktionen eine identische Signatur und Calling Convention haben. WIRKLICH identisch. Sonst Bluescreen.
              • musst Du das Dictionary, das Namen auf Funktionen abbildet, selbst implementieren.

              Ich weiß gerade nicht ob C sowas im Bauch hat; C++ hat in der STL sicherlich Klassen für ein string->func* Dictionary.

              func* ist ein Zeiger auf eine Funktion. Mein C ist arg eingerostet und die Notation ist hinreichend verquast, such Dir Beispiele. Du kannst dann im Dictionary Einträge machen aus Name und Zeiger auf Funktion, und dann an Hand dieses function pointers die Funktionen aufrufen. Ich bezweifle dass es stimmt, aber ich definiere mal für mein Beispiel, dass int(*)(int,int,int) einen Pointer auf eine Funktion darstellt, die 3 int bekommt und eins zurück gibt. Ganz weit weg von der Wahrheit bin ich vermutlich nicht. Damit hantierst Du dann so:

              int(*)(int,int,int) func = getRegisteredHandlerFor(name);
              int result = (*func)(47,11,42);
              

              Ob die Klammern um *func nötig sind weiß ich nicht - Beherrschung der Operatorenhierarchie von C gehört zu den arkanen Künsten. Und sowohl * (dereference pointer) und () (call function) sind (überladbare) Operatoren. Beide haben hohen Rang, aber aus Sicht eines kleinen plus und minus ist das so weit weg dass man nicht mehr erkennt wer nun höher ist. Lieber Klammern setzen bevor Du versuchst, ein int-Ergebnis als Pointer zu behandeln und zu dereferenzieren. Hier würde immerhin der C-AssemCompiler Einwände erheben, bevor es zum Bluescreen kommt.

              Wenn es typsicher bleiben soll, dann ist diese Suchfunktion nur für Funktionen einer Signatur geeignet. Idiomatisch für idiotisches C wäre aber, diese function pointer als void* zu speichern und bei Bedarf auf einen function pointer mit der (vermeintlich) richtigen Signatur zu casten. TU'S NICHT!

              C und C++ sind leider sehr viel sensibler, was Typen angeht, als JavaScript, PHP oder Perl.

              Eine C-Library in C++ verwendest Du übrigens prinzipiell so:

              extern "C" {
                 #include <lib.h>
              }
              

              Rolf

              --
              sumpsi - posui - clusi
              1. Alte Liebe c 😉

                Ein CGI in c kompiliert läuft genauso flott wie ein FastCGI.

                MfG

                1. Ein CGI in c kompiliert läuft genauso flott wie ein FastCGI.

                  Wenn Du nicht persistent bist, bist Du nicht persistent.

                  1. Ein CGI in c kompiliert läuft genauso flott wie ein FastCGI.

                    Wenn Du nicht persistent bist, bist Du nicht persistent.

                    Es ist mir ein besonderes Vergnügen, meine Perlklassen persistent zu machen!

                    1. Wenn Du nicht persistent bist, bist Du nicht persistent. Es ist mir ein besonderes Vergnügen, meine Perlklassen persistent zu machen!

                      Ah... welche Sicherheitslücke welchen Webservers nutzt Du genau?

    2. Hallo pl,

      Btw., in meiner Konfiguration lege ich Namen von Funktionen fest. Gibt es in c eine Möglichkeit, mit einem konfigurierten Namen eine gleichnamige Funktion aufzurufen? Also unmittelbar?

      Wäre eine DLL/ein Shared-Object für dich unmittelbar genug? Dort werden die exportierten Funktionsnamen über Strings aufgelöst, siehe https://en.wikipedia.org/wiki/Dynamic_loading bzw. für Unix konkret dlopen, dlsym und dann dlclose

      #include <dlfcn.h>
      
      typedef 
      void *lib;
      
      if ((lib = dlopen("lib<myname>.so", RTLD_LAZY))) {
          void *fct;
      
          if ((fct = dlsym(lib, "FunctionName"))) {
              // verwende das aufgelöste Symbol
              // …
          }
      
          dlclose(lib);
      }
      

      Viele Grüße
      Robert

  3. Danke Euch bisher!

    Hi, etwas OT, es geht um eine Templating Engine in c mit der ich grad die ersten Schritte tu.

    Problem macht die Funktion TMPL_write("tmplfile", 0, 0, mylist, stdout, stderr); die Templatedatei wird einfach nicht gefunden, egal ob ich mit relativen oder absoluten Pfadangaben arbeite.

    Das Problem hat sich in Luft aufgelöst 😉 D.h., es funktioniert nun tadelfrei, weiß der Geier warum das die Tage nicht ging.

    MfG

    @Robert B. ja, c ist tückisch 😉

    Speicherbreiche müssen typegerecht und akkurat definiert sein, sonst knallts 😉

    Vielleicht hat ja noch jemand ne Idee hinsichtlich assoziativer Datenstrukturen. Ich habe hier eine EAV Tabelle als indizierte Liste im Hauptspeicher, die muss jedesmal komplett durchlaufen werden wenn zu einem Entity/Attribute ein bestimmter Value gebraucht wird.