# Application Structure

*TetGenLink* is a *Mathematica* application that makes the functions of TetGen available to *Mathematica. *This is done with Wolfram *LibraryLink*, which allows TetGen to be used in a high-speed and low-memory fashion. This section will examine the details of how *LibraryLink* is used.

TetGen itself is written in C++. Its source code can be obtained from the TetGen website (http://tetgen.org). *Mathematica* uses Version 1.4.3. The interface code is written in a mixture of C++ and *Mathematica,* and this is shipped with *TetGenLink*.

You can always get to the location of *TetGenLink* by using $TetGenInstallationDirectory. This is shown in the following. First, you have to load the application.

In[1]:= |

This shows the location of *TetGenLink* for this version of *Mathematica*.

In[2]:= |

Out[2]= |

You might find this description useful for hooking up your own libraries to *Mathematica* using *LibraryLink*.

## Application Layout

*TetGenLink* is constructed as a *Mathematica* application that contains the *Mathematica* code, documentation, shared libraries, example datasets, and C++ source code. In addition, the file PacletInfo.m is a descriptor for the application. A rough outline is shown below.

TetGenLink

PacletInfo.m

TetGenLink.m

Kernel

init.m

Documentation

English

guide, reference, and tutorial pages

ExampleData

sample datasetsLibraryResources

Windows

tetgenWolfram.dll

Other SystemIDs

Source

C

C++ source code

You can find more information on the application layout and how it can be built in the documentation for the Wolfram *Workbench* at http://www.wolfram.com/products/workbench, particularly in the sections that describe application development.

*Mathematica* will find different parts of the application as necessary. For example, when the *Mathematica* Documentation Center is used, this will connect to find the documentation. When the application is loaded with Needs["TetGenLink`"], this will load the init.m file. Finally, *LibraryLink* functions such as FindLibrary will locate the appropriate dynamic library for the $SystemID on which *Mathematica* is running.

*Mathematica* Implementation

When *TetGenLink* is loaded with a command such as Needs["TetGenLink`"] or , this will load the init.m file, which in turn loads the main *Mathematica* package TetGenLink.m. The latter follows the basic structure for a *Mathematica* package, with usage information, function exports, and implementation.

When this is loaded it defines a couple of symbols, as shown below.

$TetGenInstallationDirectory = DirectoryName[ $InputFileName]

$TetGenLibrary = FindLibrary[ "tetgenWolfram"]

To see the values of these symbols, you have to load the application.

In[1]:= |

This shows the location of the *TetGenLink* application. This is set up with $InputFileName.

In[2]:= |

Out[2]= |

This shows the location of the *TetGenLink* shared library for this version of *Mathematica*. Notice how FindLibrary has resolved issues such as the $SystemID to use.

In[3]:= |

Out[3]= |

The next section loads various functions from the TetGen shared library. These all involve calls to LibraryFunctionLoad. Some, for example setPointsFun, involve sharing of data between *Mathematica* and the library, which leads to a significant saving of time and memory. You can learn more about passing data to a library in the documentation on "MTensor Input Arguments".

LoadTetGen[] :=

Module[{},

instanceFun = LibraryFunctionLoad[$TetGenLibrary,

"newTetGenInstance", {}, Integer];

deleteFun = LibraryFunctionLoad[$TetGenLibrary,

"deleteTetGenInstance", {Integer}, Integer];

fileOperationFun = LibraryFunctionLoad[$TetGenLibrary,

"fileOperation", LinkObject, LinkObject];

getPointsFun = LibraryFunctionLoad[$TetGenLibrary,

"getPointList", {Integer}, {Real,_}];

setPointsFun = LibraryFunctionLoad[$TetGenLibrary,

"setPointList", {Integer, {Real, 2, "Shared"}}, Integer];

loading more functions...

]

The body of the package is concerned with calling functions in the library. For example, the implementation of TetGenCreate checks that the library has been loaded. Then it calls the instanceFun, which is defined in the library. One point here is that the library is not loaded until a function is actually used. It does not load the library when the package is loaded. The result of the function is a TetGenExpression expression holding the ID for the instance.

TetGenCreate[] :=

Module[{},

If[ needInitialization, LoadTetGen[]];

TetGenExpression[ instanceFun[]]

]

This invokes TetGenCreate. As can be seen, the result is a handle to the instance of the TetGen object held in the library. Any calls to the library will use this handle to get the actual instance.

In[4]:= |

Out[4]= |

Here is the *Mathematica* implementation of TetGenGetPoints. It is quite simple, extracting the ID from the TetGenExpression and passing it to the function in the TetGen library.

TetGenGetPoints[ TetGenExpression[ id_]] :=

Module[{},

getPointsFun[ id]

]

## C++ Implementation

There are two parts to the C++ implementation. The source code for TetGen itself is found at the TetGen website (http://tetgen.org). This allows a version of TetGen to be built that can be used with other code. The other code provides an interface to the TetGen functions that can be used with *LibraryLink*. Its source is shipped with *TetGenLink*. You can find this in your *TetGenLink* installation using $TetGenInstallationDirectory.

To see this you must first load the application.

In[1]:= |

This is the folder that holds the C++ source for the interface.

In[2]:= |

Out[2]= |

The actual source files are shown in the following.

In[3]:= |

Out[3]= |

TetGen works by creating instances of objects that belong to the class tetgenio. These provide various methods, including adding data such as points and vertices from lists of data or from files, and carrying out various tetrahedralizations. The purpose of the interface code is support management of TetGen objects and access to their methods.

The source file tetgenInstance.cxx manages instances of TetGen objects. You can see some of its implementation in the following. This includes various header files for *LibraryLink* and for TetGen. It is going to use a hash_map from the C++ Standard Template Library to hold instances of the objects. To use this it needs to have code to load it for both the Visual C++ and GCC compilers. The hash_map allows an integer to be used as a key to find a tetgenio instance.

#include "tetgen.h"

#include "mathlink.h"

#include "WolframLibrary.h"

#include "tetgenWolframDLL.h"

#ifdef __GNUC__

#include <ext/hash_map>

namespace stdext

{

using namespace __gnu_cxx;

}

#else

#include <hash_map>

#endif

static stdext::hash_map<mint, tetgenio *> tetgenMap;

static mint tetgenListCnt = 0;

The next section contains various exports and declarations. Functions that are exported have to use a C naming scheme so they can be found by LibraryFunctionLoad; consequently, they use EXTERN_C. In addition, on Windows they need to be exported from the DLL into which they will be placed; consequently, they use DLLEXPORT.

EXTERN_C DLLEXPORT mint WolframLibrary_getVersion( ) ;

EXTERN_C DLLEXPORT mint WolframLibrary_initialize(

WolframLibraryData libData);

EXTERN_C DLLEXPORT int newTetGenInstance(

WolframLibraryData libData, mint Argc, MArgument *Args, MArgument res);

EXTERN_C DLLEXPORT int deleteTetGenInstance(

WolframLibraryData libData, mint Argc, MArgument *Args, MArgument res);

The getInstance function takes an integer and uses the hash_map to return the corresponding tetgenio instance. It is used throughout the TetGen library but is not exported from the library.

tetgenio* getInstance( mint num)

{

return tetgenMap[num];

}

Here a new instance of a TetGen object is created by calling the tetgenio constructor. It creates a new integer to use as an ID, saves the instance in the hash_map, and returns the ID. This is called directly by the *Mathematica* function TetGenCreate.

DLLEXPORT int newTetGenInstance(

WolframLibraryData libData, mint Argc, MArgument *Args, MArgument res)

{

mint newID = tetgenListCnt++;

tetgenMap[newID] = new tetgenio();

MArgument_setInteger(res, newID);

return 0;

}

## Building the TetGen Library

The *TetGenLink* library is written in very standard C++, so you could build it in a number of ways, such as a makefile or a project file. The description here will show how to build directly from *Mathematica* using the CCompilerDriver package. One advantage of this approach is that it will work for a variety of different compilers running on different types of machines.

There are a couple of issues with the build. First, one of the TetGen source files needs to be compiled with different settings. Second, the TetGen source used in *TetGenLink* has been modified to allow a function to get messages. The description here will show how to build with unmodified TetGen sources that can be found at the TetGen website (http://tetgen.org). The version used was TetGen 1.4.3.

To do the build you need to collect the TetGen sources along with the interface sources into a single directory. In this example, the symbol sourceDir gives the directory for the source, and outputDir gives the directory for the output.

In[20]:= |

You can see the actual source files as below.

In[19]:= |

Out[19]= |

Now, the CCompilerDriver` package has to be loaded.

In[22]:= |

The following sets up definitions for the input files as well as the file that is going to be compiled with no optimization.

In[23]:= |

The setting for not optimizing a file is different for different compilers. The following selects a value that will work for Visual Studio C++ and GCC compilers.

In[33]:= |

Now you can actually create the object file, with a call to CreateObjectFile.

In[34]:= |

Out[34]= |

Now you can build the library itself with CreateLibrary. The NOMESSAGEFUNCTION definition allows the library to be built with unmodified sources.

In[35]:= |

Out[35]= |

### Modifying the Source

The modification to tetgen.cxx is quite simple. Its purpose is to allow messages generated by TetGen to appear in *Mathematica*. These normally appear with printf, so the change is to overload printf to capture the text and pass it back to *Mathematica*, as done in the following.

#define printf clientprintf

typedef void (*addMessage)( char*);

static addMessage messageFun = NULL;

void setMessageFunction(addMessage fun)

{

messageFun = fun;

}

static void clientprintf( const char* mess, ...)

{

char messBuff[ 4096];

va_list ap;

va_start(ap, mess);

vsprintf( messBuff, mess, ap);

va_end(ap);

if ( messageFun != NULL) {

messageFun( messBuff);

}

}

If you add this code, you will need to remove the NOMESSAGEFUNCTION definition when building the library.