|
|||
README.EXT
entnommen, die in der Distribution enthalten ist.
Wenn Sie planen, eine Ruby Erweiterung zu schreiben, sollten Sie sich diese Datei
ansehen, um mehr Details und die aktuellsten Änderungen zu erfahren. ]VALUE
haben, der
entweder einen Zeiger auf ein Ruby-Objekt oder einen Immediate Wert (d.h. direkt
repräsentierter Wert, der Übersetzer) (so wie bei Fixnum
) darstellt.
Auf diese Weise implementiert Ruby objektorientierten Code in C:
Ein Ruby-Objekt ist eine im Speicher angelegte Struktur, die eine Tabelle von
Instanzvariablen und Informationen über die Klasse enthält.
Die Klasse selbst ist ein anderes Objekt (ebenfalls eine im Speicher angelegte Struktur), die
eine Tabelle der definierten Methoden dieser Klasse enthält.
An dieser Grundlage hängt alles in Ruby.
VALUE
einen Zeiger darstellt, zeigt er auf eine der definierten
Ruby-Objekt-Strukturen --- es gibt kein VALUE
das auf eine beliebige Struktur zeigt.
Die Strukturen für jede eingebaute Klasse sind in ``ruby.h
'' definiert und
heißen R
Klassennamen, so wie in RString
und
RArray
.
Man kann den Strukturtyp eines bestimmten VALUE
s auf verschiedene Arten
herausbekommen.
Das Makro TYPE(
obj)
liefert eine Konstante, die den C-Datentyp
des gegebenen Objektes repräsentiert: T_OBJECT
, T_STRING
und so weiter.
Die Konstanten für die eingebauten Klassen sind in der Datei ``ruby.h
'' definiert.
Man beachte, dass der Typ auf den wir uns hier beziehen ein Implementierungsdetail
darstellt --- der Typ ist etwas anderes als die Klasse des Objektes.
Wenn man sicherstellen will, dass der value Zeiger auf eine bestimmte Struktur zeigt,
kann man das Makro Check_Type
benutzen, das eine TypeError
Ausnahmebedingung wirft, wenn value nicht den erwarteten Typ besitzt.
Der Typ ist dabei eine der Konstanten T_STRING
, T_FLOAT
und so weiter:
Check_Type(VALUE value, int type)Wenn es um Geschwindigkeit geht, gibt es auch schnellere Makros, die insbesondere auf die Immediate-Werte
Fixnum
und nil
testen.
FIXNUM_P(value) -> ungleich 0 wenn value ein Fixnum ist NIL_P(value) -> ungleich 0 wenn value nil ist RTEST(value) -> ungleich 0 wenn value weder nil noch false istNochmal, beachten Sie, wir sprechen über den ``Typ '' als die C-Struktur, die einen bestimmten eingebauten Datentyp repräsentiert. Die Klasse eines Objektes ist etwas völlig anderes. Die Klassenobjekte der eingebauten Klassen werden in globalen C-Variablen mit dem Namen
rb_c
Klassenname (beispielsweise rb_cObject
) gespeichert;
Module haben die Namen rb_m
Modulname.
Es ist nicht ratsam, diese Strukturen direkt anzufassen, wie auch immer, Sie können
sie lesen, aber besser nicht beschreiben, außer Sie sind fit mit Ihrem Debugger.
Normalerweise sollte man zur Manipulation von Ruby's Daten ausschliesslich die
bereitgestellten C-Funktionen verwenden (wir werden in Kürze mehr darüber sagen).
Trotzalledem müssen Sie möglicherweise im Interesse der Geschwindigkeit
in diesen Strukturen stochern, um an die Daten heranzukommen.
Um diese C-Strukturen zu dereferenzieren, hat man den generischen
VALUE
auf die geeignete Struktur zu casten (d.h., den Typ umwandeln).
Die Datei ruby.h
enthält eine Anzahl Makros, die das für Sie erledigen, so
dass Sie die einzelnen Strukturelemente leicht dereferenzieren können.
Diese Makros heissen RKlassenname
wie in RSTRING
oder
RARRAY
. Hier ist ein Beispiel:
VALUE str, arr; RSTRING(str)->len -> Länge des Ruby Strings RSTRING(str)->ptr -> Zeiger auf dessen Inhalt RARRAY(arr)->len -> Länge des Ruby Feldes RARRAY(arr)->capa -> Kapazität des Ruby Feldes RARRAY(arr)->ptr -> Zeiger auf den Datenbereich des Feldes
Fixnum
, Symbol
, true
, false
, and nil
werden direkt (als Wert) im VALUE
gespeichert.
Fixnum
Values werden als 31-Bit Zahlen [bzw. 63-Bit auf
breiteren CPU Architekturen] gespeichert. Sie werden gebildet, indem
man die ursprüngliche Zahl um 1 Bit nach links schiebt und das niederwertigste
Bit (Bit 0) auf ``1.'' setzt.
Wenn VALUE
als Pointer auf eine spezielle Ruby-Struktur benutzt wird, ist
garantiert, dass sein niederwertigstes Bit Null ist;
Die niederwertigsten Bits aller anderen Immediate-Values sind ebenfalls Null.
Folglich verrät ein einfacher Bittest, ob ein Fixnum
vorliegt oder
eben nicht.
In der Tablle 17.1 auf Seite 176 sind einige nützliche Umwandlungs-Makros für
Zahlen und andere Standard-Datentypen aufgelistet.
Die übrigen Immediate-Values (true
, false
, und nil
)
werden in C als die Konstanten Qtrue
, Qfalse
und
Qnil
dargestellt.
Man kann eine VALUE
Variable direkt auf diese Konstanten hin testen oder
die Umwandlungs-Makros (die die geeignete Typumwandlung übernehmen) verwenden.
class Test def initialize @arr = Array.new end def add(anObject) @arr.push(anObject) end end |
#include "ruby.h" static VALUE t_init(VALUE self) { VALUE arr; arr = rb_ary_new(); rb_iv_set(self, "@arr", arr); return self; } static VALUE t_add(VALUE self, VALUE anObject) { VALUE arr; arr = rb_iv_get(self, "@arr"); rb_ary_push(arr, anObject); return arr; } VALUE cTest; void Init_Test() { cTest = rb_define_class("Test", rb_cObject); rb_define_method(cTest, "initialize", t_init, 0); rb_define_method(cTest, "add", t_add, 1); } |
ruby.h
'' einbinden um an die
nötigen Definitionen zu gelangen.
Sehen wir uns jetzt die letzte Funktion Init_Test
an.
Jede Klasse und jedes Modul definiert eine C-globale Funktion mit Namen
Init_
Namen. Diese Funktion wird immer dann aufgerufen, wenn der Interpreter
zum ersten Mal die Erweiterung Namen lädt (oder beim Programmstart
im Falle statisch gelinkter Erweiterungen). Sie wird dazu benutzt, die Erweiterung
zu initialisieren und sie in der Ruby-Umgebung bekannt zu machen.
In diesem Fall definieren wir eine neue Klasse mit dem Namen Test
,
die eine Unterklasse von Object
ist (dargestellt durch das externe Symbol
rb_cObject
; siehe auch ``ruby.h
'' für die Alternativen).
Als nächstes legen wir die zwei Instanz-Methoden add
und initialize
der Klasse Test an.
Die Aufrufe von rb_define_method
erzeugen eine Bindung zwischen
dem Ruby-Methodennamen und der C-Funktion, die sie implementiert. Auf diese Weise
bewirkt ein Aufruf der add
-Methode in Ruby den Aufruf der C-Funktion
t_add
mit einem Argument.
Auf ähnliche Weise konstruiert Ruby bei einem Aufruf von new
für diese
Klasse ein Basisobjekt und ruft danach initialize
auf, das wir hier als
die C-Funktion t_init
ohne (Ruby-) Argument definiert haben.
Gehen wir nun zurück zur Definition von initialize
. Auch wenn
wir gesagt haben, dass die Funktion keine Argumente hat, bekommt sie hier
einen Parameter! Zusätzlich zu eventuellen Ruby-Argumenten wird an jede
Methode ein erstes VALUE
-Argument übergeben, das den Empfänger für
diese Methode (das Äquivalent zu self
im Ruby-Code) enthält.
Das erste, das wir in initialize
machen, ist die Konstruktion eines Ruby-Feldes und das Setzen der Instanz-Variablen @arr
, die auf das Feld zeigt.
Wie Sie wohl erwarten, wenn Sie Ruby-Quellcode schreiben, erzeugt das
Referenzieren einer nicht existierenden Instanz-Variablen diese.
Schliesslich holt die Funktion t_add
die Instanz-Variable @arr
aus dem aktuellen Objekt und ruft
Array#push
auf,
um den übergebenen Wert an das Feld anzuhängen.
Wenn man Instanz-Variablen auf diese Weise verwendet, ist das @
-Prefix verpflichtend ---
andernfalls wird die Variable erzeugt, kann aber von Ruby aus nicht referenziert werden.
Trotz der zusätzlichen, kantigen Syntax, die C verlangt, schreiben Sie immer noch
in Ruby --- Zusätzlich zu dem Vorteil, falls erforderlich kompakten und schnellen Code
zu erzeugen, können Sie Objekte mit allen Methoden manipulieren, die sie kennen und
lieb gewonnen haben.
WARNUNG: Jede C-Funktion, die von Ruby aus aufrufbar ist,
muss ein VALUE
zurückliefern, auch dann, wenn es nur nur Qnil
ist.
Andernfalls erhalten Sie wahrscheinlich einen Core Dump (bzw. allgemeine Schutzverletzung).
Wir können die C-Version des Codes in Ruby einfach dadurch nutzen, dass
wir sie dynamisch zur Laufzeit (auf den meisten Plattformen) require
n.
require "code/ext/Test" t = Test.new t.add("Bill Chase") |
C/Ruby Datentyp Umwandlungs-Funktionen und Makros
|
eval
verwenden.
Nehmen wir an, wie hätten eine Menge von Objekten, in denen ein Flag
gelöscht werden soll.
rb_eval_string("anObject.each{|x| x.clearFlag }"); |
eval
des Strings ist), können Sie
rb_funcall(receiver, method_id, argc, ...) |
VALUE hardware_list; hardware_list = rb_ary_new(); rb_define_variable("$hardware", &hardware_list); ... rb_ary_push(hardware_list, rb_str_new2("DVD")); rb_ary_push(hardware_list, rb_str_new2("CDPlayer1")); rb_ary_push(hardware_list, rb_str_new2("CDPlayer2")); |
hardware_list
mittels $hardware
ansprechen:
$hardware |
» | ["DVD", "CDPlayer1", "CDPlayer2"] |
VALUE obj; obj = rb_ary_new(); rb_global_variable(obj); |
typedef struct _cdjb { int statusf; int request; void *data; char pending; int unit_id; void *stats; } CDJukebox; // Allokiere eine neue CDPlayer-Struktur und bringe sie online CDJukebox *CDPlayerNew(int unit_id); // Deallokiere wenn alles fertig ist (und bringe sie offline) void CDPlayerDispose(CDJukebox *rec); // Gehe zu einer CD, track und benachrichtige einen Prozess void CDPlayerSeek(CDJukebox *rec, int disc, int track, void (*done)(CDJukebox *rec, int percent)); // ... anderes Zeugs ... // Statistik Ausgabe double CDPlayerAvgSeekTime(CDJukebox *rec); |
CDJukeBox
Struktur
bedeuten, aber das ist kein Problem---wir können es wie einen undurchsichtigen Haufen von Bits
behandeln. Der Code des Herstellers weiß ja, was er damit anstellen soll und wir
müssen es nur mit uns herumschleppen.
Jedesmal, wenn eine reine C-Struktur gegeben ist, die man als Ruby-Objekt behandeln will,
sollte man sie in eine spezielle interne Ruby-Klasse mit Namen DATA
(mit dem Typ T_DATA
) einpacken.
Es gibt zwei Makros die genau das machen und ein weiteres um die Struktur wieder auszupacken.
Einpacken von C Datentypen | |
---|---|
VALUE | Data_Wrap_Struct(VALUE class, void (*mark)(), void (*free)(), void *ptr") |
Packt den gegebenen C-Datentyp ptr ein, registriert die
beiden Garbage-Collection-Routinen (siehe unten), und gibt einen VALUE-Zeiger auf
das neue Ruby-Objekt zurück.
Der C-Typ des resultierenden Objekts lautet T_DATA und seine Ruby-Klasse
ist class.
|
|
VALUE | Data_Make_Struct(VALUE class, c-type, void (*mark)(), void (*free)(), c-type *") |
Allokiert zuerst eine Struktur des angegebenen Typs, und macht danach weiter
wie Data_Wrap_Struct . c-type ist der Name des C-Datentyps, den wir
einpacken, nicht eine Variable dieses Typs.
|
|
Data_Get_Struct(VALUE obj,c-type,c-type *") | |
Liefert den ursprünglichen Zeiger. Dieses Makro stellt eine
typsichere Version des Makros DATA_PTR(obj) dar, das den
Zeiger auswertet.
|
Data_Wrap_Struct
erzeugte Objekt ist ein ganz normales
Ruby-Objekt ausser, dass es noch einen zusätzlichen C-Datentyp enthält, der
von Ruby aus nicht ansprechbar ist.
Wie man der Abb. 17.1 auf Seite 179 entnehmen kann, ist dieser C-Datentyp
von allen Instanzvariablen des Objekts getrennt.
Wie wird man es jedoch wieder los, nachdem es ja ein seperates Objekt ist,
wenn der Garbage-Collector das Objekt entsorgen will? Was ist, wenn man
Resourcen freigeben muss (Dateien schliessen, Sperren oder Inter-Prozess-Mechanismen
freigeben, oder etwas in der Art)?
void
-Zeiger, also eine Referenz auf unsere Struktur
als Parameter.
Die mark-Routine wird vom Garbage-Collector während seiner
``Markierungsphase'' aufgerufen.
Wenn unsere Struktur andere Ruby-Objekte referenziert, dann muss die mark-Routine
alle diese Objekte identifizieren, indem sie rb_gc_mark(value)
für jedes von ihnen aufruft.
Referenziert die Struktur keine weiteren Ruby-Objekte, kann man einfach
0
als Funktionszeiger übergeben.
Wenn das Objekt entsorgt werden soll, ruft der Garbage-Collector
die free-Routine auf, um es freizugeben.
Wenn Sie irgendwelchen Speicher angefordert haben (beispielsweise mittels
Data_Make_Struct
), müssen Sie eine free-Funktion bereitstellen---auch
dann, wenn es nur die free
-Funktion aus der Standard C Bibliothek ist.
Wurden komplexe Strukturen allokiert, muss die free-Funktion die Struktur abklappern,
und den kompletten angeforderten Speicher wieder freigeben.
Zuerst einmal ein einfaches Beispiel ohne jede Spezialbehandlungen.
Mit der Struktur-Definition
typedef struct mp3info { char *title; char *artist; int genre; } MP3Info; |
MP3Info
-Struktur enthält ein paar char
-Zeiger. In unserem Code initialisieren
wir sie aus zwei statischen Strings. Das impliziert, dass wir sie nicht freigeben
müssen, wenn die MP3Info
-Struktur freigegeben wird.
Wenn wir sie dynamisch allokieren würden, müssten wir auch eine free-Funktion
zu ihrer Entsorgung bereitstellen.]
MP3Info *p; VALUE info; p = ALLOC(MP3Info); p->artist = "Maynard Ferguson"; p->title = "Chameleon"; ... info = Data_Wrap_Struct(cTest, 0, free, p); |
info
ist ein VALUE
-Datentyp, ein generisches Ruby-Objekt der
Klasse Test
(in C dargestellt durch den eingebauten Typ T_DATA
).
Man kann ihn in ein Feld stecken, eine Referenz auf ihn in einem Objekt halten und so
weiter. An einer späteren Stelle im Code möchten wir die Struktur wieder benutzen,
wenn wir den zugehörigen VALUE
haben:
VALUE doit(VALUE info) { MP3Info *p; Data_Get_Struct(info, MP3Info, p); ... p->artist -> "Maynard Ferguson" p->title -> "Chameleon" ... } |
initialize
-Methode sowie
einen ``C-Konstruktor.''
Wenn wir Ruby-Quellcode schreiben würden, würden wir ein Objekt mittels eines
new
-Aufrufs allokieren und initialisieren.
Der korrespondierende Aufruf in C-Erweiterungen lautet Data_Make_Struct
.
Obwohl er den Speicher für das Objekt anfordert, ruft er nicht automatisch eine
initialize
-Routine auf. Das muss man schon selbst machen:
info = Data_Make_Struct(cTest, MP3Info, 0, free, one); rb_obj_call_init(info, argc, argv); |
initialize
-Methode dieser Klasse zu überschreiben
oder zu ergänzen.
Innerhalb initialize
ist es erlaubbar (aber nicht notwendigerweise
ratsam) den Datenzeiger direkt über DATA_PTR(obj)
zu verwenden .
Schliesslich werden Sie einen ``C-Konstruktor'' definieren---eine global
benutzbare C-Funktion, die ein Objekt mit einem einzigen bequemen Aufruf
erzeugt.
Man kann diese Funktion innerhalb des eigenen Codes verwenden oder anderen
Bibliotheks-Erweiterungen die Benutzung erlauben.
Alle eingebauten Klassen unterstützen diese Idee mit Funktionen wie
rb_str_new
, rb_ary_new
, u.s.w.
Wir können unsere eigene kreieren:
VALUE mp3_info_new() { VALUE info; MP3Info *one; info = Data_Make_Struct(cTest, MP3Info, 0, free, one); ... rb_obj_call_init(info, 0, 0); return info; } |
#include "ruby.h" #include "cdjukebox.h" VALUE cCDPlayer; static void cd_free(void *p) { CDPlayerDispose(p); } static void progress(CDJukebox *rec, int percent) { if (rb_block_given_p()) { if (percent > 100) percent = 100; if (percent < 0) percent = 0; rb_yield(INT2FIX(percent)); } } static VALUE cd_seek(VALUE self, VALUE disc, VALUE track) { CDJukebox *ptr; Data_Get_Struct(self, CDJukebox, ptr); CDPlayerSeek(ptr, NUM2INT(disc), NUM2INT(track), progress); return Qnil; } static VALUE cd_seekTime(VALUE self) { double tm; CDJukebox *ptr; Data_Get_Struct(self, CDJukebox, ptr); tm = CDPlayerAvgSeekTime(ptr); return rb_float_new(tm); } static VALUE cd_unit(VALUE self) { return rb_iv_get(self, "@unit"); } static VALUE cd_init(VALUE self, VALUE unit) { rb_iv_set(self, "@unit", unit); return self; } VALUE cd_new(VALUE class, VALUE unit) { VALUE argv[1]; CDJukebox *ptr = CDPlayerNew(NUM2INT(unit)); VALUE tdata = Data_Wrap_Struct(class, 0, cd_free, ptr); argv[0] = unit; rb_obj_call_init(tdata, 1, argv); return tdata; } void Init_CDJukebox() { cCDPlayer = rb_define_class("CDPlayer", rb_cObject); rb_define_singleton_method(cCDPlayer, "new", cd_new, 1); rb_define_method(cCDPlayer, "initialize", cd_init, 1); rb_define_method(cCDPlayer, "seek", cd_seek, 2); rb_define_method(cCDPlayer, "seekTime", cd_seekTime, 0); rb_define_method(cCDPlayer, "unit", cd_unit, 0); } |
require "code/ext/CDJukebox" p = CDPlayer.new(1) puts "Unit is #{p.unit}" p.seek(3, 16) {|x| puts "#{x}% done" } puts "Avg. time was #{p.seekTime} seconds" |
Unit is 1 26% done 79% done 100% done Avg. time was 1.2 seconds |
seek
übergeben wird, aufgerufen wird.
Innerhalb der progress
-Funktion schauen wir nach, ob innerhalb des Kontextes ein
Iterator existiert und wenn ja, dann lassen wir ihn mit dem aktuellen done-Prozent-Wert
als Argument laufen.
malloc
.
Wenn beispielsweise ALLOC_N
feststellt, dass es die angeforderte Menge an Speicher
nicht allokieren kann, dann ruft es den Garbage-Collector auf, um unbenutzen Speicher
neu zu verwenden.
Die Routine produziert einen NoMemError
wenn sie die Speicheranforderung nicht erfüllen kann oder wenn die Anforderung nicht
gültig ist.
Speicher Anforderung | |
---|---|
type * | ALLOC_N(c-type, n") |
Allokiert nc-type Objekte, wobei c-type der literale Name des C-Typs ist, keine Variable dieses Typs. | |
type * | ALLOC(c-type") |
Allokiert einen c-type und wandelt das Resultat in eine Zeiger auf diesen Typ um. | |
REALLOC_N(var, c-type, n") | |
Reallokiert nc-types und weist das Ergebnis var zu, einem Zeiger auf ein c-type. | |
type * | ALLOCA_N(c-type, n") |
Allokiert Stack-Speicher für n Objekte des Typs c-type
---dieser Speicher wird automatisch beim Verlassen der Funktion freigegeben, die
ALLOCA_N aufruft. |
extconf.rb
.
extconf.rb
um ein Makefile
für die C-Quellen in
diesem Verzeichnis zu erzeugen.
make
.
make install
.
extconf.rb
-Programm dar, das
Sie als der Entwickler erzeugen.
In die Datei extconf.rb
schreiben sie ein einfaches Programm,
das feststellt, welche Features auf dem System des Benutzers vorhanden sind und
wo diese abgelegt sein könnten.
Die Ausführung von extconf.rb
produziert ein angepasstes
Makefile
, zugeschnitten sowohl auf Ihre Applikation als auch an das
System, auf dem es übersetzt wird.
Wenn Sie das make
Kommando mit diesem Makefile
laufen lassen,
wird die Erweiterung gebaut und (optional) installiert.
Die einfachste extconf.rb
-Datei kann gerade einmal zwei Zeilen lang sein
und ist für viele Erweiterungen auch ausreichend.
require 'mkmf' create_makefile("Test") |
mkmf
-Bibliotheksmodul
(dokumentiert auf den Seiten 455ff) ein. Es enthält alle Befehle, die wir verwenden.
Die zweite Zeile erzeugt ein Makefile
für eine Erweiterung mit dem Namen ``Test''.
(Man beachte, dass ``Test'' der Name der Erweiterung ist;
das Makefile heisst immer ``Makefile.'')
Test
wird aus allen C-Quelldateien im aktuellen Verzeichnis gebaut.
Sagen wir mal, wir lassen dieses extconf.rb
-Programm in einem Verzeichnis
laufen, das nur eine einzige Quelldatei main.c
enthält.
Das Ergebnis ist ein Makefile
, das unsere Erweiterung bildet.
Auf unserem System enthält diese Datei die folgenden Befehle.
gcc -fPIC -I/usr/local/lib/ruby/1.6/i686-linux -g -O2 \ -c main.c -o main.o gcc -shared -o Test.so main.o -lc |
Test.so
, das wir
zur Laufzeit dynamisch mittels ``require
'' in Ruby einbinden können.
Beachten Sie, wie die mkmf
-Befehle plattform-spezifische Bibliotheken
und Compiler-Schalter automatisch bestimmt haben. Ganz nett, was?
Wenn dieses Basisprogramm auch für viele einfache Erweiterungen funktioniert,
muss man dennoch manchmal etwas mehr Arbeit investieren, beispielsweise, wenn die Erweiterung
Headerdateien oder Bibliotheken benötigt, die nicht zur Standardumgebung
des Compilers gehören oder wenn man Code abhängig vom Vorhandensein bestimmter
Bibliotheken oder Funktionen übersetzen will.
Häufig benötigt wird die Angabe von nicht-standard Verzeichnissen, in denen
Includedateien und Bibliotheken gefunden werden können.
Dies stellt einen zweistufiger Prozess dar.
Zuerst sollte extconf.rb
eine oder mehrere dir_config
-Kommandos
enthalten. Diese spezifizieren einen Bezeichner für eine Menge von Verzeichnissen.
Später, beim Start von extconf.rb
, sagt man mkmf
, wo die
korrespondierenden physikalisch vorhandenen Verzeichnisse auf dem jeweiligen System liegen.
Wenn extconf.rb
die Zeile dir_config(
name)
enthält,
gibt man ihm die Pfadangabe mit der Kommandozeilenoption
--with-name-include=directory
include
zum Übersetzungskommando hinzu.
--with-name-lib=directory
lib
zu den Linkerkommandos hinzu.
include
und lib
heissen, gibt es eine
Abkürzung:
--with-name-dir=directory
lib
und directory/include
zum Link- bzw. Übersetzungskommando hinzu.
--with
-Optionen beim Start von extconf.rb
angeben können,
können sie auch die --with
-Optionen verwenden, die angegeben wurden,
als Ruby für diese Maschine gebaut wurde.
Das bedeutet, dass man die Orte aller Bibliotheken herausfinden kann, die
von Ruby selbst verwendet werden.
Um das alles zu konkretisieren, sagen wir einmal, sie möchten die Bibliotheken
und Includedateien für die CD-Jukebox nutzen, die wir entwickeln.
Ihr extconf.rb
-Programm könnte dies enthalten
require 'mkmf' dir_config('cdjukebox') # .. anderes Zeugs create_makefile("CDJukeBox") |
extconf.rb
etwa so aufrufen:
% ruby extconf.rb --with-cdjukebox-dir=/usr/local/cdjb |
Makefile
geht dann davon aus, dass die Bibliotheken
in /usr/local/cdjb/lib
und die Includedateien in
/usr/local/cdjb/include
liegen.
Der dir_config
-Aufruf fügt zur Suchliste für
Bibliotheken und Includedateien die Verzeichnisse hinzu. Er kümmert
sich jedoch nicht darum, die Bibliotheken zu Ihrer Anwendung hinzuzubinden.
Um das zu bewerkstelligen, muss man eines oder mehrere have_library
-
bzw. find_library
-Kommandos verwenden.
have_library
sucht nach einem Einsprungpunkt in einer gegebenen
Bibliothek. Wenn er gefunden wurde, wird die Bibliothek an die Liste der zu
ihrer Applikation anzubindenen Bibliotheken angehängt.
find_library
arbeitet ähnlich, erlaubt Ihnen aber noch die
zusätzliche Angabe einer Liste von Verzeichnissen, in denen nach der Bibliothek
gesucht werden soll.
require 'mkmf' dir_config('cdjukebox') have_library('cdjb', 'CDPlayerNew') create_makefile("CDJukeBox") |
find_library
-Aufruf sucht eine Liste aller angegebenen Verzeichnisse
nach dem richtigen Eintrag ab. (Dies ist ein Unterschied zu have_library
,
das ausschliesslich Konfigurations-Informationen für die Suche benutzt).
Um beispielsweise ein Makefile
zu erzeugen, das X-Windows und
eine jpeg-Bibliothek verwendet, könnte extconf.rb
folgendes enthalten:
require 'mkmf' if have_library("jpeg","jpeg_mem_init") and find_library("X11", "XOpenDisplay", "/usr/X11/lib", "/usr/X11R6/lib", "/usr/openwin/lib") then create_makefile("XThing") else puts "No X/JPEG support available" end |
mkmf
-Aufrufe liefern false
, wenn sie nicht
erfolgreich waren.
Das bedeutet, dass wir ein extconf.rb
schreiben können, das nur dann
ein Makefile
erzeugt, wenn alle benötigten Teile vorhanden sind.
Die Ruby-Distribution benutzt dies auf die Weise, dass nur diejenigen Erweiterungen
übersetzt werden, die vom System auch unterstützt werden.
Möglicherweise soll Ihre Erweiterungen an die Gegebenheiten des Zielsystems
anpassbar sein.
Beispielsweise könnte unsere CD-Jukebox einen hoch performanten
MP3-Dekoder verwenden, wenn der Endbenutzer einen solchen installiert hat.
Dies lässt sich durch eine Suche nach seinen Includedateien überprüfen.
require 'mkmf' dir_config('cdjukebox') have_library('cdjb', 'CDPlayerNew') have_header('hp_mp3.h') create_makefile("CDJukeBox") |
setpriority
-Funktion nützlich, aber
sie ist nicht immer vorhanden. Mit folgendem Code lässt sich dies überprüfen:
require 'mkmf' dir_config('cdjukebox') have_func('setpriority') create_makefile("CDJukeBox") |
have_header
und have_func
definieren Preprozessor-Konstanten, wenn sie ihre Ziele finden.
Die Konstanten werden gebildet, indem das Ziel in Großbuchstaben umgewandelt
und an ``HAVE_'' angehängt wird.
Der C-Code kann daraus Nutzen ziehen mit Konstruktionen wie:
#if defined(HAVE_HP_MP3_H) # include <hp_mp3.h> #endif #if defined(HAVE_SETPRIORITY) err = setpriority(PRIOR_PROCESS, 0, -10) #endif |
mkmf
-Befehlen erschlagen werden können, kann das Programm
auch direkt Strings an die globalen Variablen $CFLAGS
und
$LFLAGS
anhängen, die an den Compiler und den Linker
übergeben werden.
%%--------------------------
du
auch machen solltest.
Erweiterungs-Verzeichnis unter ext/
in der Ruby-Distribution. Wenn
man einfach nur die Dteien extconf.rb
und MANIFEST
in seinem
Verzeichnis hat, so läuft die Ruby-Build-Prozedur automatisch und wird die
daraus resultierende Makefile-
Datei benutzen, um die Erweiterung zu
erzeugen und im Ruby-Bibliotheks-Pfad zu installieren (das ist ein versions- und maschinen-
abhängiger Pfad, bei uns ist das /usr/local/lib/ruby/1.6/i686-linux
.
ext/Setup
in der Distribution und fügen Sie Ihr
Verzeichnis zur Liste der Erweiterungen in ihm hinzu, bevor Sie Ruby
neu erzeugen.
Die Erweiterungen, die in Setup
aufgeführt sind, werden statisch
zu Ruby gebunden. Sollten Sie das dynamische Binden abschalten und alle
Erweiterungen statisch binden wollen, editieren Sie ext/Setup
so,
dass es die folgende Option enthält.
option nodynamic |
#include "ruby.h" main() { /* ... our own application stuff ... */ ruby_init(); ruby_script("embedded"); rb_load_file("start.rb"); while (1) { if (need_to_do_ruby) { ruby_run(); } /* ... run our app stuff */ } } |
ruby_init()
aufrufen.
Allerdings sind auf manchen Plattformen vorher noch spezielle Schritte nötig:
#if defined(NT) NtInitialize(&argc, &argv); #endif #if defined(__MACOS__) && defined(__MWERKS__) argc = ccommand(&argv); #endif |
main.c
der Ruby-Distribution kann man andere spezielle Defines
oder Initialisierungen finden, die für Ihre Plattform benötigt werden.
Schnittstellenroutinen für eingebettetes Ruby | |
---|---|
void | ruby_init(") |
Initialisiert den Interpreter. Diese Funktion sollte vor allen anderen Ruby-bezogenen Funktionen aufgerufen werden. | |
void | ruby_options(int argc, char **argv") |
Setzt die Kommandozeilen-Optionen für den Ruby-Interpreter. | |
void | ruby_script(char *name") |
Setzt den Namen des Ruby-Skripts (sowie $0 ) auf name.
|
|
void | rb_load_file(char *file") |
Lädt die angegebene Datei in den Interpreter. | |
void | ruby_run(") |
Startet den Interpreter. |
rb_protect
, rb_rescue
und
verwandte Funktionen werden auf Seite 194 dokumentiert.
Als Beispiel für die Einbettung eines Ruby-Interpreters in ein anderes
Programm dient auch eruby
, das ab Seite 149 beschrieben ist.
ID
: Man erhält eine
ID
für einen String aus rb_intern
und die Rekonstruktion
des Names aus einer ID
durch rb_id2name
.
Nachdem nahezu alle dieser C-Funktionen Ruby-Äquivalente besitzen, die
anderswo in diesem Buch detailiert beschrieben sind, sind die Erklärungen
hier kurz gehalten.
Beachten Sie ausserdem, dass die folgende Liste nicht vollständig ist.
Es gibt viel mehr Funktionen---zu viele um sie alle zu dokumentieren, wie sich
herausstellt.
Wenn Sie eine Methode benötigen, die Sie hier nicht finden, fahnden Sie in
``ruby.h
'' oder ``intern.h
'' nach wahrscheinlichen Kandidaten.
Am Ende oder nahe am Ende jeder Quelldatei steht auch eine Menge von Methoden-Definitionen,
die die Anbindung von Ruby-Methoden an C-Funktionen beschreiben.
Sie können die C-Funktionen direkt aufrufen oder nach Wrapper-Funktionen suchen,
die dies intern tut.
Die folgende Tabelle, basierend auf der Tabelle in README.EXT
,
zeigt die wichtigsten Quelldateien im Interpreter.
Definieren von Objekten | |
---|---|
VALUE | rb_define_class(char *name, VALUE superclass") |
Definiert eine neue Klasse auf oberstem Level mit dem angegebenen Namen
name sowie der Oberklasse superclass.
(Für die Klasse Object benutzt man rb_cObject ).
|
|
VALUE | rb_define_module(char *name") |
Definiert ein neues Modul auf oberstem Level mit dem angegebenen Namen name. | |
VALUE | rb_define_class_under(VALUE under, char *name, VALUE superclass") |
Definiert eine eingebettete Klasse unterhalb der Klasse oder des Moduls under. | |
VALUE | rb_define_module_under(VALUE under, char *name") |
Definiert ein eingebettetes Modul unterhalb der Klasse oder des Moduls under. | |
void | rb_include_module(VALUE parent, VALUE module") |
Fügt das angegebenene Modul module in die Klasse oder das Modul parent ein. | |
void | rb_extend_object(VALUE obj, VALUE module") |
Erweitert das Objekt obj durch das Modul module. | |
VALUE | rb_require(const char *name") |
Gleichbedeutend mit ``require name.''
Liefert Qtrue oder Qfalse zurück.
|
argc | Funktions-Prototyp | |||||||
0..17 | VALUE func(VALUE self, VALUE arg...) |
|||||||
Die C-Funktion wird mit dieser Anzahl tatsächlicher Argumente gerufen. | ||||||||
-1 | VALUE func(int argc, VALUE *argv, VALUE self) |
|||||||
Die C-Funktion bekommt eine variable Anzahl Argumente, die als C-Feld übergeben werden. | ||||||||
-2 | VALUE func(VALUE self, VALUE args) |
|||||||
Die C-Funktion bekommt eine variable Anzahl Argumente, die als Ruby-Feld übergeben werden. | ||||||||
rb_scan_args
nutzen, um an die eigentlichen Argumente
zu gelangen (siehe unten).
Definition von Methoden | ||
---|---|---|
void | rb_define_method(VALUE classmod, char *name, VALUE(*func)(), int argc") | |
Definiert eine Instanzmethode namens name in der Klasse oder dem Modul classmod, die durch die C-Funktion func implementiert wird, welche argc Argumente erwartet. | ||
void | rb_define_module_function(VALUE classmod, char *name, VALUE(*func)(), int argc)") | |
Definiert eine Methode namens name in der Klasse classmod, implementiert durch die C-Funktion func, die argc Argumente erwartet. | ||
void | rb_define_global_function(char *name, VALUE(*func)(), int argc") | |
Definiert eine globale Funktion (eine private Methode von Kernel )
mit Namen name, die durch die C-Funktion func implementiert wird und die
argc Argumente erwartet.
|
||
void | rb_define_singleton_method(VALUE classmod, char *name, VALUE(*func)(), int argc") | |
Definiert eine Singleton-Methode in der Klasse classmod mit dem angegeben Namen name, implementiert durch die C-Funktion func, die argc Argumente erwartet. | ||
int | rb_scan_args(int argcount, VALUE *argv, char *fmt, ...") | |
Durchläuft die Argumentliste und weist das Ergebnis Variablen zu ähnlich wie scanf :
fmt ist eine Zeichenkette bestehend aus Null, einem oder zwei Ziffern gefolgt von
einigen Spezifikationsbuchstaben.
Die erste Ziffer gibt die Anzahl der unbedingt nötigen Argumente an; die zweite
ist die Anzahl optionaler Argumente.
Das Zeichen ``*'' bedeutet, dass der Rest der Argumente in ein Ruby-Feld gepackt werden soll.
Ein ``&'' heißt, dass ein angehängter Code-Block übernommen und der angegebenen Variablen
zugewiesen wird (Wurde kein Code-Block angegeben, wird Qnil zugewiesen).
Nach dem fmt-String werden (genau wie bei scanf ) Zeiger auf VALUE
erwartet, denen dann die Argumente zugewiesen werden.
|
||
void | rb_undef_method(VALUE classmod, const char *name") | |
Löscht die angegebene Methode name aus der angegebenen Klasse oder dem Modul classmod. | ||
void | rb_define_alias(VALUE classmod, const char *newname, const char *oldname") | |
Definiert einen Alias für oldname in der Klasse oder dem Modul classmod. |
Definition von Variablen und Konstanten | ||
---|---|---|
void | rb_define_const(VALUE classmod, char *name, VALUE value") | |
Definiert eine Konstante namens name mit dem Wert value in der Klasse oder dem Modul classmod. | ||
void | rb_define_global_const(char *name, VALUE value") | |
Definiert eine globale Konstante namens name mit dem Wert value. | ||
void | rb_define_variable(const char *name, VALUE *object") | |
Exportiert die Adresse des in C erzeugten angegeben Objektes object in den Ruby-Namensraum als name. Aus Rubysicht ist es eine globale Variable, folglich sollte der Namen name mit einem führenden Dollar-Zeichen beginnen. Stellen Sie sicher, dass sie Ruby's Regeln für gültige Variablennamen berücksichtigen; Variablen mit illegalem Namen sind von Ruby aus nicht ansprechbar. | ||
void | rb_define_class_variable(VALUE class, const char *name, VALUE val") | |
Definiert eine Klassenvariable namens name
(die ein ``@@ '' Prefix enthalten muss) in der angegeben Klasse
class und initialisiert sie mit dem Wert value.
|
||
void | rb_define_virtual_variable(const char *name, VALUE(*getter)(), void(*setter)()") | |
Exportiert eine virtuelle Variable in den Ruby-Namensraum als globale Variable
$name. Es existiert kein Speicherplatz für diese Variable.
Versuche, sie zu lesen bzw. schreiben rufen die angegebenen Funktionen
mit den folgenden Prototypen auf:
|
||
void | rb_define_hooked_variable(const char *name, VALUE *variable, VALUE(*getter)(), void(*setter)()") | |
Definiert Funktionen, die aufgerufen werden, wenn eine Variable variable
gelesen oder geschrieben wird.
Siehe auch rb_define_virtual_variable .
|
||
void | rb_define_readonly_variable(const char *name, VALUE *value") | |
Genau wie rb_define_variable , aber die Variable ist von Ruby aus nur lesbar.
|
||
void | rb_define_attr(VALUE variable, const char *name, int read, int write") | |
Erzeugt Zugriffsmethoden für die angegebene Variable variable, mit Namen name. Wenn read ungleich null ist, erzeuge eine Lesemethode; Wenn write ungleich null ist, erzeuge eine Schreibmethode. | ||
void | rb_global_variable(VALUE *obj") | |
Registriert die angegebene Adresse beim Garbage-Collector. |
Aufruf von Methoden | |
---|---|
VALUE | rb_funcall(VALUE recv, ID id, int argc, ...") |
Ruft die Methode auf, die durch id gegeben ist im Objekt recv mit der angegebenen Variablenanzahl argc und den spezifizierten Argumenten (möglicherweise auch gar keinem). | |
VALUE | rb_funcall2(VALUE recv, ID id, int argc, VALUE *args") |
Ruft die Methode auf, die durch id gegeben ist im Objekt recv mit der angegebenen Variablenanzahl argc und den Argumenten im C Feld args. | |
VALUE | rb_funcall3(VALUE recv, ID id, int argc, VALUE *args") |
Wie rb_funcall2 , ruft aber keine privaten Methoden auf.
|
|
VALUE | rb_apply(VALUE recv, ID name, int argc, VALUE args") |
Ruft die Methode auf, die durch id gegeben ist im
Objekt recv mit der angegebenen Variablenanzahl argc und
den Argumenten im Ruby Array args.
|
|
ID | rb_intern(char *name") |
Liefert die ID zu einem gegebenen Namen name.
Wenn der Namen nicht existiert wird ein Eintrag in der Symboltabelle für ihn erzeugt.
|
|
char * | rb_id2name(ID id") |
Liefert den Namen zu einer gegebenen id. | |
VALUE | rb_call_super(int argc, VALUE *args") |
Ruft die aktuelle Methode in der Oberklasse des aktuellen Objekts auf. |
Exceptions (Ausnahmen) | |
---|---|
void | rb_raise(VALUE exception, const char *fmt, ...") |
Wirft eine Ausnahmebedingung exception.
Die angegebene Zeichenkette fmt sowie die übrigen
Argumente werden genauso interpretiert wie bei printf .
|
|
void | rb_fatal(const char *fmt, ...") |
Wirft eine Fatal -Ausnahme, die den Prozess beendet.
Es werden keine rescue- aber ensure-Blöcke abgearbeitet.
Die angegebene Zeichenkette fmt sowie die übrigen
Argumente werden genauso interpretiert wie bei printf .
|
|
void | rb_bug(const char *fmt, ...") |
Beendet den Prozess sofort---es werden keinerlei Behandlungsroutinen aufgerufen.
Die angegebene Zeichenkette fmt sowie die übrigen
Argumente werden genauso interpretiert wie von printf .
Sie sollten diese Funktion nur dann aufrufen, wenn ein fataler Fehler entdeckt wurde.
Sie schreiben aber keine Programme mit fatalen Fehlern, oder doch?
|
|
void | rb_sys_fail(const char *msg") |
Wirft eine plattform-spezifische Ausnahmebedingung, die zum letzten bekannten Systemfehler gehört, zusammen mit der Meldung msg. | |
VALUE | rb_rescue(VALUE (*body)(), VALUE args, VALUE(*rescue)(), VALUE rargs") |
Führt den Block body mit den Argumenten args aus. Wenn eine
StandardError -Ausnahme auftritt,
führe auch den Block rescue mit den Argumenten rargs aus.
|
|
VALUE | rb_ensure(VALUE(*body)(), VALUE args, VALUE(*ensure)(), VALUE eargs") |
Ruft den Block body mit den Argumenten args aus. Egal, ob eine Ausnahme auftritt oder nicht, führe immer den ensure Block mit den Argumenten rargs aus, sobald body beendet ist. | |
VALUE | rb_protect(VALUE (*body)(), VALUE args, int *result") |
Ruft den Block body mit den Argumenten args auf und liefert etwas ungleich Null im Ergebnis result, wenn dabei irgendeine Ausnahme auftrat. | |
void | rb_notimplement(") |
Wirft eine NotImpError -Ausnahme um anzuzeigen, dass die
eingeschlossene Funktion noch nicht implementiert oder auf dieser Plattform nicht
verfügbar ist.
|
|
void | rb_exit(int status") |
Beendet Ruby mit dem Status status. Wirft eine SystemExit -Ausnahme und ruft alle registrierten exit Funktionen sowie finalize-Funktionen auf.
|
|
void | rb_warn(const char *fmt, ...") |
Produziert (immer) eine Warnmeldung auf dem Standardfehlerausgang.
Die Zeichenkette fmt sowie die übrigen Argumente werden wie bei printf
interpretiert.
|
|
void | rb_warning(const char *fmt, ...") |
Produziert nur dann eine eine Warnmeldung auf dem Standardfehlerausgang,
wenn Ruby mit dem -w flag aufgerufen wurde.
Die Zeichenkette fmt sowie die übrigen Argumente werden wie bei printf
interpretiert.
|
Iteratoren | |
---|---|
void | rb_iter_break(") |
Springt aus dem umgebenden Iterator-Block heraus. | |
VALUE | rb_each(VALUE obj") |
Ruft die each Methode für das Objekt obj auf.
|
|
VALUE | rb_yield(VALUE arg") |
Übergibt die Ausführung an den Iterator-Block im momentanen Kontext und übergibt das Argumente arg an ihn. Mehrere Werte können als Feld übergeben werden. | |
int | rb_block_given_p(") |
Liefert true (wahr) wenn yield einen Block im momentanen Kontext
ausführen würde---d.h., wenn ein Code-Block an die aktuelle Methode
übergeben wurde und seine Ausführung möglich ist.
|
|
VALUE | rb_iterate(VALUE (*method)(), VALUE args, VALUE (*block)(), VALUE arg2") |
Ruft die Methode method mit den Argumenten args und dem Block
block auf. Ein yield aus dieser Methode ruft
block mit den Argumenten args und einem weiteren Argument arg2 auf.
|
|
VALUE | rb_catch(const char *tag, VALUE (*proc)(), VALUE value") |
Gleichbedeutend mit Ruby's catch .
|
|
void | rb_throw(const char *tag , VALUE value") |
Äquivalent zu Ruby's throw .
|
Zugang zu Variablen | |
---|---|
VALUE | rb_iv_get(VALUE obj, char *name") |
Liefert die Instanz-Variable namens name (der mit
einem ``@ ''-Prefix beginnen muss) des Objekts obj.
|
|
VALUE | rb_ivar_get(VALUE obj, ID name") |
Liefert die Instanz-Variable name des Objekts obj. | |
VALUE | rb_iv_set(VALUE obj, char *name, VALUE value") |
Setzt den Wert der Instanz-Variablen namens name (der mit einem
``@ ''-Prefix beginnen muss) im Objekt obj auf value, der
auch zurückgeliefert wird.
|
|
VALUE | rb_ivar_set(VALUE obj, ID name, VALUE value") |
Setzt den Wert der Instanz-Variablen namens name (der mit einem
``@ ''-Prefix beginnen muss) im Objekt obj auf value, der
auch zurückgeliefert wird.
|
|
VALUE | rb_gv_set(const char *name, VALUE value") |
Setzt die globale Variable namens name (das ``$ ''-Prefix ist
optional) auf value. Liefert value zurück.
|
|
VALUE | rb_gv_get(const char *name") |
Liefert den Wert der globalen Variable name (das ``$ ''-Prefix ist
optional).
|
|
void | rb_cvar_set(VALUE class, ID name, VALUE val") |
Setzt die Klassenvariable name in der Klasse class auf value. | |
VALUE | rb_cvar_get(VALUE class, ID name") |
Liefert den Wert der Klassenvariablen name der Klasse class. | |
int | rb_cvar_defined(VALUE class, ID name") |
Liefert Qtrue wenn die Klassenvariable
name in class bereits definiert wurde; ansonsten liefert es
Qfalse .
|
|
void | rb_cv_set(VALUE class, const char *name, VALUE val") |
Setzt die Klassenvariable namens name
(der mit einem ``@@ ''-Prefix beginnen muss) in der Klasse
class auf den Wert value.
|
|
VALUE | rb_cv_get(VALUE class, const char *name") |
Liefert den Wert der Klassenvariablen namens name
(der mit einem ``@@ ''-Prefix beginnen muss) der Klasse class.
|
Status von Objekten | |
---|---|
OBJ_TAINT(VALUE obj") | |
Markiert das gegebene Objekt obj als tainted (verdorben). | |
int | OBJ_TAINTED(VALUE obj") |
Liefert etwas ungleich Null, wenn obj als tainted markiert ist. | |
OBJ_FREEZE(VALUE obj") | |
Markiert das Objekt obj als frozen (eingefroren/unveränderbar). | |
int | OBJ_FROZEN(VALUE obj") |
Liefert etwas ungleich Null, wenn obj als frozen markiert ist. | |
Check_SafeStr(VALUE str") | |
Wirft eine SecurityError -Ausnahme, wenn der derzeitige Sicherheitslevel > 0 und str
als tainted markiert ist, oder eine TypeError -Ausnahme, wenn str kein T_STRING ist.
|
|
int | rb_safe_level(") |
Liefert den momentanen Sicherheitslevel zurück. | |
void | rb_secure(int level") |
Wirft eine SecurityError -Ausnahme, wenn level <= derzeitiger Sicherheitslevel.
|
|
void | rb_set_safe_level(int newlevel") |
Setzt den derzeitigen Sicherheitslevel auf newlevel. |
Häufig eingesetzte Methoden | |
---|---|
VALUE | rb_ary_new(") |
Liefert ein neues Array der Defaultgröße.
|
|
VALUE | rb_ary_new2(long length") |
Liefert ein neues Array der angegebenen Länge length.
|
|
VALUE | rb_ary_new3(long length, ...") |
Liefert ein neues Array der angegebenen Länge length, das mit den
restlichen Argumenten bevölkert wird.
|
|
VALUE | rb_ary_new4(long length, VALUE *values") |
Liefert ein neues Array der angegebenen Länge length,
das mit den Werten des C-Feldes values besetzt wird.
|
|
void | rb_ary_store(VALUE self, long index, VALUE value") |
Speichert den Wert value an die Indexposition index des Feldes self. | |
VALUE | rb_ary_push(VALUE self, VALUE value") |
Hängt den Wert value ans Ende des Feldes self an. Liefert value. | |
VALUE | rb_ary_pop(VALUE self") |
Entfernt und liefert das letzte Element des Feldes self. | |
VALUE | rb_ary_shift(VALUE self") |
Entfernt und liefert das erste Element des Feldes self. | |
VALUE | rb_ary_unshift(VALUE self, VALUE value") |
Hängt den Wert value am Beginn des Feldes self ein. Liefert value. | |
VALUE | rb_ary_entry(VALUE self, long index") |
Liefert das index.te Elemente des Feldes self. | |
int | rb_respond_to(VALUE self, ID method") |
Liefert einen Wert ungleich Null, wenn self auf die Methode method antwortet. | |
VALUE | rb_thread_create(VALUE (*func)(), void *data") |
Startet die Funktion func in einem neuen Thread, wobei data als Argument übergeben wird. | |
VALUE | rb_hash_new(") |
Liefert einen neuen, leeren Hash (assoziatives Feld).
|
|
VALUE | rb_hash_aref(VALUE self, VALUE key") |
Liefert das zum Schlüssel key in self gehörende Element. | |
VALUE | rb_hash_aset(VALUE self, VALUE key, VALUE value") |
Setzt in self den Wert des zum Schlüssel key gehörenden Elements auf value. Liefert value. | |
VALUE | rb_obj_is_instance_of(VALUE obj, VALUE klass") |
Liefert Qtrue , falls obj eine Instanz der Klasse klass ist.
|
|
VALUE | rb_obj_is_kind_of(VALUE obj, VALUE klass") |
Liefert Qtrue , falls klass die Klasse oder eine der Oberklassen
von obj ist.
|
|
VALUE | rb_str_new(const char *src, long length") |
Liefert einen neuen String , der mit den length Zeichen
aus src initialisiert wird.
|
|
VALUE | rb_str_new2(const char *src") |
Liefert einen neuen String , der mit dem nullterminierten
C string src initialisiert wird.
|
|
VALUE | rb_str_dup(VALUE str") |
Liefert ein neues String Objekt, das eine Kopie von str enthält.
|
|
VALUE | rb_str_cat(VALUE self, const char *src, long length") |
Hängt die length Zeichen von src an den
String self an. Liefert self.
|
|
VALUE | rb_str_concat(VALUE self, VALUE other") |
Hängt other an
den String self an. Liefert self.
|
|
VALUE | rb_str_split(VALUE self, const char *delim") |
Liefert ein Feld von String -Objekten, die durch Auftrennen von
self an den Stellen delim entstehen. |