Marc Reichelt: CGI mit C++

Hallo an alle,

seit kurzem bin ich (neben meinem Grundpraktikum, das mich momentan voll beansprucht) dabei, native Maschinen-Programme für meinen Webserver zu entwickeln. Die ersten Beispiele sind _sehr_ einfach gehalten, und darum für jeden nachvollziehbar, der selbst Interesse daran hätte.

Ein erstes Beispiel ist online:
http://marcreichelt.de/cgi-test/test_get.cgi?Parameter=Wert

Das Programm nimmt einfach nur alle GET-Daten entgegen und gibt sie aus.
Der Quelltext des Programms ist auf drei Dateien aufgeteilt (ich stelle den Code zudem hier online, damit der Quellcode gleich ohne externen Editor mit Syntax-Highlighting angeschaut werden kann):

<code src="test_get.cpp">

  
#include <iostream>  
#include "CGIUtil.cpp"  
  
int main() {  
 std::cout << "Content-type: text/plain;charset=utf-8" << std::endl;  
 std::cout << std::endl;  
  
 CGIUtil* cgiUtil = CGIUtil::getInstance();  
  
 std::cout << cgiUtil->getGETString() << std::endl;  
  
 delete cgiUtil;  
 cgiUtil = 0;  
  
 return 0;  
}  

~~~</code>  
  
  
<code src="[CGIUtil.cpp](http://marcreichelt.de/cgi-test/CGIUtil.cpp)">  
~~~c++
  
#include "CGIUtil.h"  
#include <string>  
  
CGIUtil* CGIUtil::instance = 0;  
  
CGIUtil::CGIUtil() {  
 getPointer = getenv("QUERY_STRING");  
}  
  
CGIUtil* CGIUtil::getInstance() {  
 if (instance == 0) {  
  instance = new CGIUtil();  
 }  
  
 return instance;  
}  
  
std::string CGIUtil::getGETString() {  
 if (getPointer == 0) {  
  return "";  
 } else {  
  return std::string(getPointer);  
 }  
}  

~~~</code>  
  
  
<code src="[CGIUtil.h](http://marcreichelt.de/cgi-test/CGIUtil.h)">  
~~~c++
  
#ifndef CGIUtil_h  
#define CGIUtil_h  
  
#include <string>  
  
class CGIUtil {  
 private:  
  static CGIUtil* instance;  
  char* getPointer;  
  char* postPointer;  
  CGIUtil();  
 public:  
  static CGIUtil* getInstance();  
  std::string getGETString();  
};  
  
#endif  

~~~</code>  
  
Kompiliert habe ich das Ganze mit diesem Befehl:  
g++-4.0 -O2 -Wall test\_get.cpp -o test\_get.cgi  
  
  
Eventuell besteht hier bei einigen Leuten Interesse daran, selbst native Programme als CGI laufen zu lassen - ganz getreu der Technik des SELFHTML Forums... ;-)  
Für diese kann dies als eine kleine Einführung in CGI-Programmierung mit nativen Programmen dienen.  
  
  
Grüße  
  
Marc Reichelt || <http://www.marcreichelt.de/>  

-- 
Linux is like a wigwam - no windows, no gates and an Apache inside!  
  
[Selfcode](http://emmanuel.dammerer.at/selfcode.html): ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
  1. Hallo nochmals,

    um die Programme mit der Endung ".cgi" vom Apache Server ausführen zu lassen, ist im entsprechenden Ordner natürlich noch eine .htaccess mit folgendem Inhalt erforderlich (die entsprechenden Rechte der CGI-Dateien natürlich vorrausgesetzt):

    <code src=".htaccess">
    AddHandler cgi-script .cgi
    DirectoryIndex index.cgi
    Options +ExecCGI
    </code>

    Grüße

    Marc Reichelt || http://www.marcreichelt.de/

    --
    Linux is like a wigwam - no windows, no gates and an Apache inside!
    Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
  2. 你好 Marc,

    #include "CGIUtil.cpp"

    Nichts für Ungut, aber das tut man so nicht ;) Mache eine Header-Datei, in der du das Interface definierst, und binde dann hinterher die beiden Object-Dateien zusammen. Die Header-Datei hast du ja sogar... du benutzt sie nur nicht... also: #include "CGIUtil.h", dann so kompilieren:

    g++ -c -O2 -W -Wall -o cgiutil.o CGIUtil.cpp
    g++ -c -O2 -W -Wall -o test_get.o test_get.cpp
    g++ -O2 -W -Wall -o test_get.cgi cgiutil.o test_get.o

    Das hat den Vorteil, dass du einerseits sauber modularisieren kannst (was machst du, wenn dein Projekt mal n C++-Dateien hat? Sobald du die CGIUtils.cpp in mehr als eine Datei einbindest, gibts Ärger...) und andererseits kannst du so sehr einfach eine Makefile draus bauen, die nur das neu machen würde, das sich geändert hat:

    CFLAGS=-O2 -W -Wall

    all: test_get.cgi

    test_get.cgi: test_get.o cgiutil.o
        g++ $(CFLAGS) -o test_get.cgi cgiutil.o test_get.o

    test_get.o: test_get.cpp CGIUtil.h
        g++ -c $(CFLAGS) -o test_get.o test_get.cpp

    cgiutil.o: CGIUtil.cpp CGIUtil.h
        g++ -c $(CFLAGS) -o cgiutil.o CGIUtil.cpp

    (Die vier Leerzeichen sind eigentlich Tabulatoren. Und das müssen sie auch bleiben - wichtig! ;) Bei Eingabe von "make" (passendes Make-Programm vorrausgesetzt) wird dann das neu kompiliert, was sich geändert hat, und zum Schluss nur neu gebunden. Beschleunigt den Entwicklungsprozess ungemein, glaub mir ;)

    再见,
     克里斯蒂安

    --
    Das Malheur mit dem Open Source | Frühling
    Swen Wacker: Denn wer 'ne Blacklist hat, muss halt daran denken, dass er manches nicht sieht... und vor dem posten die Realitaet einschalten
    http://wwwtech.de/