Das könnte ein schöner Tag werden. Den Wortspreizern zeigt
http://www.deppenleerzeichen.de/, wo der Bindestrich hängt.
http://www.einzelhandelspoesie.de/ und
http://www.dooden.de/ sind
ebenfalls Empfehlungen aus der aktuellen Ausgabe der c't und damit
nicht besonders originell, jedenfalls nicht, wenn ich sie hier
aufführe. Aber solches Bestreben gilt es zu fördern,
also liste ich die Verweise auf diese Projekte, bis deren
Google-Ranking
durch die Decke geht.
Wer schon ein bißchen meine TWiki-Seiten durchstöbert hat, hat sicher
bemerkt, daß TWiki-URLs ihre Eigenheiten haben. Statt eines Verweises auf
eine statische HTML-Seite bezeichnet eine TWiki-URL den Aufruf von CGI-Scripts
mit Parametern:
http://www.clausbrod.de/Atari # typisch "statisch"
http://www.clausbrod.de/cgi-bin/view.pl/Atari/ # TWikifizierte URL
Ohne Zweifel tippt und merkt sich die erste Form viel leichter. TWiki basiert
aber nun einmal auf von CGI-Scripts dynamisch erzeugten HTML-Seiten. Das ist
natürlich noch lange kein Grund, mit diesen Interna hausieren zu gehen,
indem man solche URLs nach außen gibt, denn so etwas ist definitiv
uncool. Aber es zu beheben,
ist leider gar nicht so einfach.
Nach einigem Kopfkratzen und Geschraube funktioniert die obige erste URL-Form
sogar. Naja, so ein bißchen jedenfalls.
Eine kleine Sammlung von
RedirectMatch-Anweisungen
(Apache-Modul
mod_alias) in der
passenden
.htaccess-Datei macht es möglich, die einfache URL-Form
zu verwenden. Die wird dann von
RedirectMatch
in die Langform verwandelt,
und die richtige Seite erscheint. Soweit nicht schlecht, nur: In der URL-Eingabezeile
des Browsers erscheint nun wieder die Langform der URL.
Das liegt, so denke ich, daran, daß
RedirectMatch
die URL zuerst
umformt und dann an den aufrufenden Browser zurückschickt mit dem Vermerk,
daß sich die URL geändert hat - worauf der Browser
es mit der neuen URL einfach nochmal versucht. (Wer mich bei einer
dumpfbackigen Fehlinterpretation erwischt, grätsche hier bitte
beherzt dazwischen.) Und das macht die "neue", also lange URL eben wieder
sichtbar.
Der nahe Verwandte von
RedirectMatch
namens
ScriptAliasMatch
scheint
ohne Rekurs zum Client zu funktionieren - aber sobald ich
entweder
ScriptAlias
oder
ScriptAliasMatch
verwende, schlagen
alle Zugriffe
auf meine Website mit einem Serverfehler fehl. Das liegt wohl daran, daß
ScriptAlias
und
ScriptAliasMatch
nur in der Konfigurationsdatei
httpd.conf
,
aber nicht in
.htaccess
erlaubt sind. Auf
httpd.conf
habe ich aber bei
meinem Provider (Strato) keinerlei Zugriff, muß mich also mit
.htaccess
begnügen.
Die einschlägigen TWiki-Tricks zu diesem Thema verweisen meist auf
das Apache-Modul
mod_rewrite.
Zwar setzt Strato auf dem kleinen Stück Server, das ich dort gemietet habe,
tatsächlich Apache ein, jedoch ist
mod_rewrite
dort nicht installiert.
Offenbar kann man es auch nicht nachinstallieren, sondern braucht dazu einen
eigenen Root-Server - was ich mir vorläufig nicht antun will.
Fürs Erste begnüge ich mich also mit dem bisher Erreichten. Links,
die in TWiki-Seiten auftauchen, verweisen ebenfalls auf kurze URLs und werden dann
ebenfalls dynamisch umgeleitet; das habe ich mit einer kleinen Änderung in
DefaultPlugin erreicht. Und wer
weiß, vielleicht inspirieren mich ja die folgenden
einschlägigen TWiki-Artikel:
PS: Inzwischen habe ich die Artikel gelesen. Leider keine Lösung darin
zu finden.
Auf meine alten Tage befasse ich mich doch tatsächlich auch noch mit solchen Dingen
wie Microsoft .NET. Wenn man mir das während meines Studiums und meiner hyperaktiven
Atari-Zeit prophezeit hätte...
Nun denn. Kommt mir neulich so ein häßlicher kleiner Käfer entgegen. Und das kam so:
Wenn man Werte vom Typ
bool
aus "managed code" in "unmanaged code" per Marshaling
überträgt, geht das in so richtig großen Stil schief.
Der "managed code" (in C++) stellt einen einfachen Aufruf zur Verfügung mit einem
Rückgabewert vom Typ
bool
. Vereinfachter Beispielcode:
public __gc __interface IBool {
bool Foo(void);
};
public __gc class Booltest : public IBool
{
public:
Booltest() {}
bool Foo(void) { return false; }
};
Diesen Code übersetzt man in ein Assembly, und daraus produziert man mittels
regasm
eine Typenbibliothek (tlb-Datei). Gleichzeitig registriert
regasm
das Assembly; und hinterher
werfen wir das Assembly in den Schlund des GAC. Auszug aus der erzeugten
Typenbibliothek:
interface IBool : IDispatch {
[id(0x60020000)]
HRESULT Foo([out, retval] unsigned char* pRetVal);
};
Man beachte, daß der Typ des Rückgabewerts vom
bool
nach
unsigned char
abgeändert wurde. Soweit keine Überraschung, denn
Nathan
erwähnt in seiner COM-Interop-Bibel, daß der Marshaling-Typ für Werte vom Typ
bool
eben
UnmanagedType::U1
ist - also
unsigned char
.
So richtig übel wird es aber, wenn ich nun
Foo()
aus einem COM-Client zu rufen versuche.
Der COM-Client erzeugt sich einen "smart pointer" vom Typ
IBoolPtr
und ruft dann
Foo()
:
bool ret = pBool->Foo();
Nach diesem Aufruf ist allerdings der Stack beschädigt. Läft man im Einzelschritt
durch den Code, merkt man, daß der COM-Client denkt, der Rückgabewert sei ein
Byte gross; daher legt er auch nur ein Byte auf dem Stack für die Ergebnisvariable
ret
an. Der Marshaling-Code allerdings schreibt munter
vier Bytes!
Das gleiche passiert, wenn man im "managed code" das Attribut
[MarshalAs(UnmanagedType::U1)]
ausdrücklich anwendet. Microsoft beschreibt
im
Knowledge-Base-Artikel 823071
einen möglicherweise verwandten Fehler beim Marshaling von
bool-Werten,
allerdings hilft der vorgeschlagene Hotfix in meinem Fall nicht. Ändere
ich den Marshaling-Typ auf
U2
, wird's noch lustiger: Dann überschreibt
der Marshaler zwar keinen Speicher mehr, räumt dafür aber den Stackpointer
nach dem Aufruf nicht mehr auf!
Hat jemand Ideen?
(Siehe auch
http://groups.google.de/groups?hl=de&lr=&threadm=10gd95ifu6uoe9a%40corp.supernews.com.)
PS: Einige Zeit später hat uns Microsoft bestätigt, daß das in der Tat
ein Fehler in .NET 1.1 war. .NET 2.0 macht's nun richtig.
Next month: Click
here.