Anzeige:
Ergebnis 1 bis 6 von 6

Thema: getopt zweimal im gleichen Programm verwenden?

  1. #1
    Registrierter Benutzer
    Registriert seit
    21.07.2006
    Beiträge
    46

    getopt zweimal im gleichen Programm verwenden?

    Bei meinem Projekt ist es notwendig, dass öfters während der Laufzeit Parameter geparst werden müssen, was ich mit getopt umsetzen möchte. (Hintergrund: diese Aufrufargumente stammen von einem Client, der sie via IPC an den Serverprozess übermittelt, wo diese interpretiert werden sollen. So ist es möglich, einen einfachen Client zu schreiben, der keine komplexe API, sondern nur diese Strings verstehen muss)

    getopt erlaubt das aber anscheinend nicht, beim zweiten Aufruf gibt die Funktion sofort -1 zurück, was so viel wie "alle parameter wurden geparst) bedeutet.
    Wie kann ich getopt also mitteilen, dass hier jetzte neue Parameter zu parsen sind?

    Minimalbeispiel:
    Code:
    #include <iostream>
    #include <getopt.h>
    
    void parseArgs(int argc, char** argv)
    {
      int c;
      while((c = getopt(argc, argv, "a")) != -1)
      {
        if(c == 'a')
        {
          std::cout << "found a\n";
        }
      }
    }
    
    int main()
    {
      char **argv1 = new char*[2];
      argv1[0] = new char[50];
      strcpy(argv1[0], "progname");
      argv1[1] = new char[50];
      strcpy(argv1[1], "-a");
    
      parseArgs(2,argv1);
    
    
      char **argv2 = new char*[2];
      argv2[0] = new char[50];
      strcpy(argv2[0], "progname");
      argv2[1] = new char[50];
      strcpy(argv2[1], "-a");
    
      parseArgs(2,argv2);
    }
    Die Ausgabe des Beispiels ist nur "found a", beim gewünschten Verhalten sollte das aber 2x ausgegeben werden.

  2. #2
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von totycro Beitrag anzeigen
    Bei meinem Projekt ist es notwendig, dass öfters während der Laufzeit Parameter geparst werden müssen, was ich mit getopt umsetzen möchte. (Hintergrund: diese Aufrufargumente stammen von einem Client, der sie via IPC an den Serverprozess übermittelt, wo diese interpretiert werden sollen. So ist es möglich, einen einfachen Client zu schreiben, der keine komplexe API, sondern nur diese Strings verstehen muss)...
    Das ist AFAIK prinzipiell unmöglich. Die Kommandozeilenparameter werden prinzipiell nur beim Start des Programms übergeben und können auch nur 1x ausgewertet werden. Wenn Du Parameter zur Laufzeit auswerten willst, dann musst Du sie dem Programm auch zur Laufzeit übergeben können. getopt ist für Deine Zwecke unbrauchbar, denk Dir was Anderes aus (stdin usw.).

    Jan

  3. #3
    Registrierter Benutzer
    Registriert seit
    21.07.2006
    Beiträge
    46
    Zitat Zitat von jan61 Beitrag anzeigen
    Moin,

    Das ist AFAIK prinzipiell unmöglich. Die Kommandozeilenparameter werden prinzipiell nur beim Start des Programms übergeben und können auch nur 1x ausgewertet werden. Wenn Du Parameter zur Laufzeit auswerten willst, dann musst Du sie dem Programm auch zur Laufzeit übergeben können. getopt ist für Deine Zwecke unbrauchbar, denk Dir was Anderes aus (stdin usw.).

    Jan
    Danke für deine Antwort, ich hab bis jetzt immer bei Projekten bestimmter Größe gern getopt verwendet, was wären denn die Alternativen dazu? (die Anforderungen sind im wesentlichen die, welche von getopt erfüllt werden; eine zusätzliche Dependency möchte ich falls möglich vermeiden)

  4. #4
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    hm, also so wie ich die getopt-Manpage interpretiere, kannst Du das mit getopt tatsächlich nicht machen:
    The getopt() function parses the command line arguments. Its arguments argc and argv are the argument count and array as passed to the main() function on program invocation.
    Zuerst mal musst Du Dir überlegen, wie Du zur Laufzeit die zusätzlichen Schalter an das Programm übergibst, z. B. über eine Datei, STDIN, Pipe ... Und dann kannst Du doch selbst festlegen, in welcher Form die ankommen sollen, das Format sollte so sein, dass Du es leicht parsen kannst. Beispiel "schalter[=wert]":
    Code:
      char **kv = new char*[3];
      kv[0] = new char[20];
      strcpy(kv[0], "schalter1=wert1");
      kv[1] = new char[20];
      strcpy(kv[1], "schalter2");
      kv[2] = NULL;
    
      int i;
      for (i=0; kv[i] != NULL; i++) {
        if (strchr(kv[i], '=') != NULL) {
          char *v = strchr(kv[i], '=')+1;
          *strchr(kv[i], '=') = 0;
          std::cout << "key=" << kv[i] << "; value=" << v << "\n";
        }
        else
          std::cout << "key " << kv[i] << " is set\n";
      }
    Jan

  5. #5
    Registrierter Benutzer
    Registriert seit
    21.07.2006
    Beiträge
    46
    k, den Parser werd ich dann wohl einfach selbst schreiben.

    Um die Parameter an das Hauptprogramm zu übergeben verwende ich DBUS, genauer gesagt die DBUS-Implementierung von Qt. Das Programm hat keine GUI, also ist DBUS sowie Qt eigentlich Overkill, früher oder später möchte ich diese Dependencies los werden.
    In meinem Studium wurde mal die Verwendung von Message Queues durchgenommen, das sollte für meine Zwecke genügen, aber echte Praxiserfahrung damit hab ich noch keine. Welchen IPC-Mechanismus könntet ihr mir denn empfehlen?

  6. #6
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    das ist ein wenig abhängig davon, was Du übergeben willst und wie umfangreich die Daten sind. Für einfache An-/Ausschalter könnten Signale reichen, ansonsten Message Queues oder bei umfangreichen Daten eher Shared Memory. Daneben gibt es natürlich auch andere Mechanismen, wie Programme Daten austauschen können - Stichwort tcp/ip, Sockets, (Named) Pipes.

    Jan

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •