Ruby/Win32API
Die Win32API Klasse bietet ein Rubyinterface für Funktionen einer C-Bibliothek, welches mit der Instanzmethode +call+ die Funktionen ausführen kann. Die Klasse selbst ist in Ruby geschrieben, und benutzt die DL-Bibliothek aus der Ruby Standard-API, welche selbst ein Interface für "dynamic linker" zur Verfügung stellt. Nach Ruby Version 1.9.1, wird die Win32API Klasse als deprecated verzeichnet, und es wird empfohlen direkt mit dem DL-Interface zu arbeiten. Besonders interessant ist diese Klasse für den RPG Maker XP und VX. Sie ist nämlich im RGSS eingebunden, und stellt somit die Möglichkeit zur Verfügung die Spiele mit reinem C-Code zu unterstützen, was annähernd unbegrenzte Möglichkeiten bietet.
Verwendungsbeispiele finden sich unter anderem bei den Codeschnippseln des RGSS.
Inhaltsverzeichnis
Überblick: Libraries
Libraries (Befehls-Bibliotheken) sind "shared" (zur Benutzung mit verschiedenen Applikationen freigegebene) OS-Komponenten, die dem Programmierer spezielle Funktionen anbieten. Zum Beispiel kann eine Library Befehle zum einfachen Handhaben und Manipulieren von Bildern enthalten oder dem Speichern unter Dialog aufzurufen. Jedes OS bietet eine Anzahl an "shared" Libraries, um das Programmierer-Leben zu vereinfachen. Mit Ruby ist es möglich, diese externen Libraries einfach und dynamisch zu benutzen! Der Grund für die Nützlichkeit von Libraries liegt darin, dass sie separat von den Applikationen sind, aber zwischen diesen geteilt ("shared") werden. Eine Library-Datei muss nur einmal in den Speicher geladen werden, was Speicherplatz spart, insbesondere bei häufig benutzten Libraries. Sie nützen auch dem Programmierer, da dies bedeutet, dass Sie nicht jedes Mal das Rad wieder neu erfinden brauchen, wenn Sie ein cleveres Feature in Ihrem Programm verwenden wollen. Libraries sind auch nützlich, um Prozeduren - die von mehreren Programmen benötigt werden - aufzunehmen und zu aktualisieren, ohne das eigentliche Hauptprogramm verändern zu müssen. Unter dem Windows OS sind "shared" Libraries gut bekannt unter dem Namen 'DLL's, einer Abkürzung für "Dynamic Link Libraries".
Konstanten
DLL
Ein Hash, der handles zu allen bisher genutzen DLL Funktionen hält.
Die im RGSS eingebundene Win32API Klasse, scheint diese Konstante nicht zu haben.
Klassen Methoden
new
Win32API.new( dll_name, function_name, in, out)
| Argument | Beschreibung |
|---|---|
| dll_name' | Wird ersetzt durch ein String-Objekt, der den Namen der DLL enthält. |
| function_name | Wird ersetzt durch ein String-Objekt, der den Namen der Funktion enthält. |
| in | Kann entweder ein bis zu 16-elementiges Array- oder String-Objekt sein. |
| out | Wird ersetzt durch 1-elementiges String-Objekt, dass wie in eines der vier Buchstaben ist. |
Parameter
dll_name
Ein String mit dem Dateinamen der zu öffnenden Shared Library. Normalerweise, wenn Sie keinen Pfad als Teil des Dateinamens mit angeben, wird die Library im Verzeichnis Ihres Programms gesucht, und wenn sie sich nicht dort befindet, wird das Verzeichnis der Systembibliotheken durchsucht. Die Systemvariable %sysdir% besitzt u.a. einen Pfad als Wert, der durchsucht wird.
Die Suche ist nicht case-sensitive. Die Angabe einer Dateiendung wie ".dll" ist nicht nötig.
function_name
Ein String in dem der Name der Funktion steht, die zur Benutzung geladen werden soll.
in
Eine Signatur, welche Datentypen an die Funktion gesendet werden sollen. Es gibt 4 Arten:
| Name | Buchstabe | Steht für welches Ruby-Objekt als Parameter? |
|---|---|---|
| Long/Number | L, l, N oder n | Fixnum- oder Bignum-Objekt |
| Integer/Ganzzahl | I oder i | Fixnum- oder Bignum-Objekt |
| Pointer/Zeiger | P oder p | String-Objekt |
| Void | V oder v | Falls kein Parameter von der Funktion erwartet wird. |
Anmerkung: L, N und I werden intern gleich behandelt.
Statt "v" funktioniert auch "" sowie "0" oder nil. Gebräuchlich bleibt aber "v".
out
Das ist der Typ des Rückgabewertes. Also die Art, ob ein Pointer/Zeiger oder Zahl als Antwort erwartet wird. Die Arten sind die gleichen wie bei +in+.
Methoden
call
call( [args]* )
Ruft die API Funktion mit den angegebenen Parametern auf, welche vom Typ der Signatur von der Initialisierung entsprechen müssen.
Die Rückgabe hängt von der aufgerufenen Funktion ab, ihr Typ entspricht aber der Signatur, die beim Initialize als +out+ angegeben wurde.
Call
Alias von Win32API#call.
Anmerkungen zu den Parametern
Oft nehmen die Funktionen der C-Bibliotheken nur Zeiger auf bestimmte Werte, oder Strukturen, bzw. geben diese zurück. Intern verwendet Ruby fast nur Zeiger, aber auf unserer Rubyebene sind sie uns fremd. Allerdings gibt uns Ruby ja kein Werkzeug was nur manchmal funktioniert, weswegen vorgesorgt wurde: In Ruby werden Zeiger auf Werte oder Strukturen durch Strings represäntiert, welche eine Sequenz aus Bytes halten. Arrays haben hierfür die Funktionen +pack+ und Strings die Funktion +unpack+ welche beliebige Werte in den String packen, sodas C-Funktionen mit ihnen Arbeiten können, und wieder auspacken, sodass Ruby damit arbeiten kann.
Ein Beispiel
# API Funktion holen get_cursor_pos = Win32API.new('user32', 'GetCursorPos', 'p', 'v') # Die Funktion erwartet einen Zeiger auf 2 LONGs, # das ist ein Datentyp der Zahlen speichert. point_struct = [0,0].pack("LL") # C Funktion aufrufen get_cursor_pos.call( point_struct ) # Die Funktion schreibt nun in den Speicherbereich # auf den der mitgegebene Zeiger zeigt, die zwei # Longs, bzw. in den angegebenen String. # Nun holen wir die Zahlen wieder raus; x, y = point_struct.unpack("LL") # Ausgeben und fertig print "Punkt (#{x}|#{y})\n"
Quellcode
Quellcode aus Ruby 1.8.6
# -*- ruby -*- require 'dl' class Win32API DLL = {} def initialize(dllname, func, import, export = "0") prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI").sub(/^(.)0*$/, '\1') handle = DLL[dllname] ||= DL::Handle.new(dllname) @sym = handle.sym(func, prototype) end def call(*args) import = @sym.proto.split("", 2)[1] args.each_with_index do |x, i| args[i] = nil if x == 0 and import[i] == ?S args[i], = [x].pack("I").unpack("i") if import[i] == ?I end ret, = @sym.call(*args) return ret || 0 end alias Call call end
Verwandte Themen
Links
Microsoft hat mit MSDN (Microsoft Developer Network) eine riesige Übersichts- und Funktionsreferenz zur Windows API.