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.

Remark 1. It is possible that the communication protocol changes in the future. In that case, the data structures TeXmacs_exports_1 and package_exports_1 will be replaced by data structures TeXmacs_exports_n and package_exports_n, where n is the version of the protocol. These structures will always have the abstract data structures TeXmacs_exports and package_exports in common, with information about the versions of the protocol, TeXmacs and your package.

The dynlink plug-in

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 C++ file dynlink.cpp, it contains a string

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.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".