Dynamic libraries |
Instead of connecting your system to TeXmacs using a pipe, it is also possible to connect it as a dynamically linked library. Although communication through pipes is usually easier to implement, more robust and compatible with gradual output, the second option is faster.
In order to dynamically link your application to TeXmacs, you should follow the TeXmacs communication protocol, which is specified in the following header file:
$TEXMACS_PATH/include/TeXmacs.h
In this file it is specified that your application should export a data structure
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;
which contains an installation routine for your application, as well as an evaluation routine for further input (for more information, see the header file). TeXmacs will on its turn export a structure
typedef struct TeXmacs_exports_1 {
char* version_protocol; /* "TeXmacs communication protocol 1" */
char* version_TeXmacs;
} TeXmacs_exports_1;
It is assumed that each application takes care of its own memory management. Hence, strings created by TeXmacs will be destroyed by TeXmacs and strings created by the application need to be destroyed by the application.
The string version_protocol should contain "TeXmacs communication protocol 1" and the string version_package the version of your package. The routine install will be called once by TeXmacs in order to initialize your system with options options. It communicates the routines exported by TeXmacs to your system in the form of a pointer to a structure of type TeXmacs_exports_1. The routine should return a status message like
"yourcas-version successfully linked to TeXmacs"
If installation failed, then you should return NULL and *errors should contain an error message.
The routine evaluate is used to evaluate the expression what inside a TeXmacs-session with name session. It should return the evaluation of what or NULL if an error occurred. *errors either contains one or more warning messages or an error message, if the evaluation failed. The formats being used obey the same rules as in the case of communication by pipes.
Finally, the configuration file of your plug-in should contain something as follows:
(plugin-configure myplugin
(:require (url-exists? (url
"$LD_LIBRARY_PATH"
"libmyplugin.so")))
(:link "libmyplugin.so"
"myplugin_exports" "")
further-configuration)
Here myplugin_exports is a pointer to a structure of the type package_exports_1.
The dynlink plug-in gives an example of how to write dynamically linked libraries. It consists of the following files:
dynlink/Makefile dynlink/progs/init-dynlink.scm dynlink/src/dynlink.cpp
The Makefile contains
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 that running it will create a dynamic library dynlink/lib/libdynlink.so from dynlink.cpp. The tmsrc variable should contain $TEXMACS_PATH, so as to find the include file TeXmacs.h. The configuration file init-dynlink.scm simply contains
(plugin-configure dynlink
(:require (url-exists? (url
"$LD_LIBRARY_PATH"
"libtmdynlink.so")))
(:link "libtmdynlink.so"
"dynlink_exports" "")
(:session "Dynlink"))
As to the
static char* output= NULL;
with the last output, the initialization 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;
}
the evaluation 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;
}
and the data structure with the public exports:
package_exports_1 dynlink_exports= {
"TeXmacs communication protocol 1",
"Dynlink 1",
dynlink_install,
dynlink_eval
};
Notice that the application takes care of the memory allocation and deallocation of output.