Ruby/DL

Aus Scientia
Wechseln zu: Navigation, Suche

Das RGSS3 stellt neben Win32API auch diese Erweiterungsbibliothek zum Aufrufen von Funktionen in DLLs zur Verfügung.

Allgemein

DL ist mächtiger als Win32API. Es werden von ihr u.a. die Aufrufkonventionen cdecl und stdcall und auch Rückruffunktionen unterstützt. Fehlende Dokumentation und die hohe Komplexität für viele Anwendungen sind jedoch ein großer Nachteil.

RGSS

Im RGSS3 ist nur der C-Teil dieser Erweiterungsbibliothek von Haus aus verfügbar. Der Ruby-Teil, der z.B. Import von Funktionen anhand eines Prototyps ermöglicht, muss nachträglich hinzugefügt werden.

Klasse / Modul Beschreibung
DL Hauptmodul, das dynamische Speicherzuordnung beherrscht und Konstanten u.a. für die Typen beinhaltet
DL::DLError allgemeine Exception
DL::DLTypeError Exception, falls ein unbekannter oder inkorrekter Typ bei einem Aufruf verwendet wurde
DL::Handle Klasse zum Laden einer DLL und zum Herausfinden der Adresse einer Funktion
DL::CFunc Interface für eine C-Funktion
DL::CPtr Interface für einen C-Zeiger

Beispiel

command line

# Name der Win32-Funktion, die die Unicode-Version der Kommandozeilenzeichenkette zurück gibt
# Doku: <http://msdn.microsoft.com/en-us/library/windows/desktop/ms683156%28v=vs.85%29.aspx>
name = 'GetCommandLineW'
# die DLL laden
handle = DL::Handle.new 'kernel32'
# Adresse unsere Funktion erhalten
address = handle.sym(name)
# getcommandlinew ist ein Ruby-Interface für die Funktion
# Rückgabedatentyp ist zwar LPWSTR (Zeiger auf wchar_t), DL bietet jedoch nur VOIDP (void *).
# Aufrufkonvention der Win32-API ist stdcall (Standard ist cdecl)
getcommandlinew = DL::CFunc.new(address, DL::TYPE_VOIDP, name, :stdcall)
# die Funktion GetCommandLineW aufrufen
# die Funktion erwartet keine Argumente, darum bleibt das Array leer
cmdline = getcommandlinew.call([])
# Wir haben nun einen Zeiger auf die Unicodekommandozeilenzeichenkette.
# Die Länge brauchen wir jedoch auch (bei ANSI/char wäre das nicht nötig, aber es ist nicht mehr 1970).
# wcslen gibt einen Wert mit dem Typ size_t zurück. Im RGSS3 gibt es DL::TYPE_SIZE_T jedoch nicht.
wcslen = DL::CFunc.new(DL.dlopen('msvcrt').sym('wcslen'), DL::TYPE_INT)
# wcslen gibt die Länge in Buchstaben zurück. Wir brauchen sie in Bytes! (sizeof(wchar_t) == 2)
length = wcslen.call([cmdline]) * 2
# durch den Pointer und die Stringlänge in Byte können wir den adressierten Speicher
# in einen Ruby-String konvertieren. Danach kodieren wir den String von UTF-16 (Win32-API) nach UTF-8 (RGSS3).
command_line = DL::CPtr.new(cmdline, length).to_str.encode!('UTF-8', 'UTF-16LE')
p command_line  # => "Game.exe  console test RPG ツクール"

Adresse der Bitmap-Pixel

class Bitmap
  def address
    data = DL::CPtr.new((object_id << 1) + 16).ptr
    info = (data + 8).ptr
    (info + 16).ptr.to_i  # letzte Scanline!
  end
end

Für weitere Informationen und den verbreiteteren Weg siehe den Abschnitt "Die Bitmap-Struktur" auf Bitmap.

Links