Großhochzeit: C#, Delphi, Assembler und COM

Ein Feature das mit großer Wahrscheinlichkeit in zukünftigen Versionen von .NET noch implementiert werden wird, ist (managed/inline-) Assembler in seine Projekte einzubinden. In einigen Hochsprachen mit „echtem“ Compiler ist dies bereits seit vielen Jahren Standard: C++, TurboPascal, FreePascal, Delphi, freeBASIC, usw.

Zudem findet man in alten mächtigen Source-Code-Archiven oft bis zur Perversion optimierte Algorithmen, die der Autor bereits in Inline-ASM implementiert hat. Es wäre doch zu schade diese nicht weiter nutzen zu können…

Folgenden Code fand ich im SwissDelphiCenter:
http://www.swissdelphicenter.ch/de/showcode.php?id=2049
(Ein Instring-Algorithmus von Vanja Fuckar, 100% inline-ASM)

Delphi erlaubt es mit sehr wenig Aufwand einen Quelltext direkt als COM-Programmbibliothek zu kompilieren. Heraus kommt eine dll-Datei (hier: „InString_dll.dll“) die ich nun in mein .NET-Projekt einbinde mittels:


[System.Runtime.InteropServices.DllImport("InString_dll.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int InString(int StartPosition, string Source, string Pattern);

Aufgerufen wird diese externe statische Funktion wie üblich z.B. mit:


Console.WriteLine(InString(0, "Testautotesttesttest", "auto").ToString());

Einen Haken hat das (vor)kompilieren von Inline-Assembler: Es gibt keine Gewährleistung, dass diese Programmbibliothek auch auf anderen Prozessorarchitekturen bzw. -familien ausgeführt werden kann, als auf der sie kompiliert wurde.
Exemplarisch habe ich dafür die .NET-Anwendung auf einem AMD Athlon X2 64bit ausgeführt: der JIT-Debugger spuckt eine Exception aus, die mir eine ungültige Typenumwandlung bestätigt.
Auf einem Intel Pentium 4 HT wiederum lief der Quelltext einwandfrei.
Anmerkung dazu: Die Programmbibliothek habe ich auf einer Intel Pentium M kompiliert, die bekannterweise nicht aus der Familie der NetBurst-Architekturen stammt.

Nachtrag: Auf einem Pentium Xeon (NetBurst) lief die Anwendung ebenfalls einwandfrei.

Delphi: Winamp-Titel auslesen

Winamp-Titel in Delphi auslesen
Winamp-Titel in Delphi auslesen

Um mit Delphi den aktuellen Winamp-Titel auszulesen benötigt man nur eine kleine Funktion. Der Zugriff erfolgt über die WinAPI.


function GetWinampFilename(): String;
var
    hwndWinamp, ProcessHandle: THandle;
    dat2: array[0..500] of Char;
    temp, MPointer: Cardinal;
begin
  //Bitte nicht wundern, die Fensterbezeichnung ist korrekt und funktioniert bei allen Winamp-Versionen:
  hwndWinamp:=FindWindow('Winamp v1.x',nil);
  MPointer:= SendMessage(hwndWinamp,WM_USER,SendMessage(hwndWinamp,WM_USER,0 , 125), 212);
  GetWindowThreadProcessId(hwndWinamp,ProcessHandle);
  hwndWinamp:= OpenProcess(PROCESS_ALL_ACCESS,False,ProcessHandle);
  ReadProcessMemory(hwndWinamp, Pointer(MPointer), @dat2,500,temp);
  CloseHandle(hwndWinamp);
  Result:= String(dat2);
end;

Parse/Split in Delphi 6

Ein großes Manko an Delphi (bis zur .NET-isierung) war/ist eine fehlende Funktion für das zuverlässige und schnelle Parsing von Strings. Folgende Funktion begleitet mich bereits seit 2002 durch fast alle Delphi-Projekte:


function Parse(Char, S: string; Count: Integer): string;
var
  I: Integer;
  T: string;
begin
  if S[Length(S)] <> Char then
    S := S + Char;
  for I := 1 to Count do
  begin
    T := Copy(S, 0, Pos(Char, S) - 1);
    S := Copy(S, Pos(Char, S) + 1, Length(S));
  end;
  Result := T;
end;