# 4 Creating a DLL

## 4.1 Compiling the C++ program

The Mozart system provides `oztool` which we recommend you invoke instead of calling the C/C++ compiler directly:

> `oztool c++ -c getenv.cc -o getenv.o`

`oztool` takes care of many unpleasant details for you; for example, it supplies the compiler with the appropriate option for the generation of position independent code.

## 4.2 Creating a dynamic library

Now, we create a shared object from the compiled object file obtained above. Again you should invoke `oztool` rather than call the linker directly:

> `oztool ld getenv.o -o getenv.so`

This takes care of many ugly details (especially on Windows where they could easily drive you nuts). Actually, you should really create a shared object file with, as suffix, the platform for which it was created. For example:

> `oztool ld getenv.o -o getenv.so-linux-i486`

The reason is that the Oz module manager was designed to support platform independent module import specifications, but, of course, native modules must be resolved to platform dependent implementations. The default resolution strategy achieves this by means of platform suffixes.

In order to write portable makefiles, you can use `oztool` to print out the platform name:

> `oztool platform`

Thus a portable way to create the shared object is:

> `oztool ld getenv.o -o getenv.so-`oztool platform``

## 4.3 Linking a native module

In the last step we make the native module available by linking it into Oz. Lines 16--23 in Program 2.1 are needed to declare the export signature of the native module. A function named `oz_init_module` must be exported by every native module: this function will be called when the module is linked into Oz. It can be used to do some module dependent initialization and has to return an array whose elements are of type `OZ_C_proc_interface`; the end of the array must be terminated by an empty structure. The array describes the signature of the functions being exported from the module:

> `typedef struct {
> const char * name;
> short inArity;
> short outArity;
> OZ_CFun func;
> } OZ_C_proc_interface;`

`name` is a string naming the feature under which the native function will be accessible from Oz (see below). `inArity` and `outArity` specify the number of input and output arguments. `func` is a pointer to the function being exported.

Now we can link our module into Oz by executing:

> `declare
> [Goodies]={Module.link ['./getenv.so{native}']}`

This will lazily load the module upon first access and bind `Goodies` to a record with a single (since we exported only one function) feature named `getenv` (this is derived from the value of the `name` field of `OZ_C_proc_interface`). Now we can call it like this:

> `{Browse {Goodies.getenv 'HOME'}}`

The module can also be imported by any Oz module:

> `functor
> import G at 'getenv.so{native}'
> define
> ... {G.getenv ...} ...
> end`

Note that the url used in the import specification does not supply the platform suffix, but adds the `{native}` annotation. The module manager (or more precisely the resolver) will remove the annotation and replace it with the suffix appropriate for the current platform.