Dynamisch ladbare Bibliotheken |
Die Kommunikation zwischen TeXmacs und einer Anwendung kann auSSer über eine „Pipeline“ auch dadurch erfolgen, dass die Anwendung als „dynamically linked library”, DLL, eingebunden wird. Pipelines sind meist leichter zu implementieren, oft sehr robust und flexibel in Bezug auf Daten, die nur nach und nach erzeugt werden. Aber DLLs sind schneller.
Um eine Anwendung dynamisch mit TeXmacs zu linken, sollten Sie dem TeXmacs Kommunikations-Protokoll folgen, das in folgenden Datei
include/TeXmacs.h
definiert ist.
Darin ist spezifiziert, dass die Anwendung folgende Datenstruktur exportieren soll:
typedef struct package_exports_1 {
char* version_protocol; /* "TeXmacs communication protocol 1" */
char* version_package;
char* (*install) (TeXmacs_exports_1* TeXmacs,
char* options, char** errors);
char* (*evaluate) (char* what, char* session, char** errors);
} package_exports_1;
Sie enthält sowohl eine Installationsroutine für die Anwendung als auch eine Evaluierungsroutinen für zusätzliche Eingabe. (Mehr Informationen finden Sie in der Datei include/TeXmacs.h). TeXmacs exportiert folgende Struktur:
typedef struct TeXmacs_exports_1 {
char* version_protocol; /* "TeXmacs communication protocol 1" */
char* version_TeXmacs;
} TeXmacs_exports_1;
Jedes Programm hat für sein Speicher-Management selbst zu sorgen. Zeichenketten, die TeXmacs erzeugt, müssen von TeXmacs gelöscht werden. Das gilt entsprechend für die Anwendung.
Die Zeichenkette version_protocol sollte „TeXmacs communication protocol 1" und die Zeichenkette version_package die Version Ihrer Anwendung enthalten.
Die Funktion install wird ein einziges Mal von TeXmacs mit den Optionen options aufgerufen, um Ihre Anwendung zu initialisieren. Es überträgt die Routinen, die von TeXmacs exportiert werden, als TM. Diese Routine sollte, sofern erfolgreich, eine Statusmeldung zurückgeben, z.B.:
"Ihre CAS-Version wurde erfolgreich in TeXmacs eingebunden"
Wenn die Installation ohne Erfolg blieb, sollten Sie NULL zurückgeben und *errors sollte eine erklärende Meldung enthalten.
Die evaluate-Funktion dient zur Evaluierung von what in einer TeXmacs-Sitzung mit dem Namen session. Sie sollte das Ergebnis der Evaluierung von what zurückgeben, falls erfolgreich, oder NULL, wenn ein Fehler auftrat. *errors kann, je nach Verlauf der Evaluierung, eine oder mehrere Warnungen enthalten oder eine Fehlermeldung, wenn die Evaluierung versagte. Die Formate sind die gleichen wie im Fall der Kommunikation über Pipelines.
Schließlich sollte die Konfigurations-Datei des Plugins noch so etwas wie das folgende enthalten:
(plugin-configure myplugin
(:require (url-exists? (url
"$LD_LIBRARY_PATH"
"libmyplugin.so")))
(:link "libmyplugin.so"
"myplugin_exports" "")
further-configuration)
Hier ist myplugin_exports ein Zeiger auf eine Struktur vom Typ package_exports_1.
Das Beispiel Plugin dynlink zeigt, wie dynamisch ladbare Bibliotheken geschrieben und benutzt werden. Es besteht aus den Dateien:
dynlink/Makefile dynlink/progs/init-dynlink.scm dynlink/src/dynlink.cpp
Das Makefile enthält die Zeilen
tmsrc = /home/vdhoeven/texmacs/src/TeXmacs
CXX = g++
LD = g++
lib/libtmdynlink.so: src/dynlink.cpp
$(CXX) -I$(tmsrc)/include -c src/dynlink.cpp
-o src/dynlink.o
$(LD) -shared -o lib/libtmdynlink.so
src/dynlink.o
so dass dynlink.cpp zu einer dynamisch linkbaren Datei (DLL) dynlink/lib/libdynlink.so kompiliert wird. Die tmsrc Variable sollte so gesetzt sein, dass die include-Datei TeXmacs.h gefunden wird. Die Konfigurations-Datei init-dynlink.scm enthält die folgenden Zeilen
(plugin-configure dynlink
(:require (url-exists? (url
"$LD_LIBRARY_PATH"
"libtmdynlink.so")))
(:link "libtmdynlink.so"
"dynlink_exports" "")
(:session "Dynlink"))
Die
static char* output= NULL;
mit der letzten Ausgabe, die Initialisierungs-Routine
char*
dynlink_install (TeXmacs_exports_1* TM, char* opts, char** errs) {
output= (char*) malloc (50);
strcpy (output, "\2verbatim:Started dynamic link\5");
return output;
}
die Evaluierungs-Routine
char*
dynlink_eval (char* what, char* session, char** errors) {
free (output);
output= (char*) malloc (50 + strlen (what));
strcpy (output, "\2verbatim:You typed ");
strcat (output, what);
strcat (output, "\5");
return output;
}
und die Daten-Struktur den Exporten
package_exports_1 dynlink_exports= {
"TeXmacs communication protocol 1",
"Dynlink 1",
dynlink_install,
dynlink_eval
};
Beachten Sie bitte, dass bei der Ausgabe die Anwendung für die Reservierung und die Freigabe von Speicher zu sorgen hat.