Appendix H. Wrapping C Libraries with gmmproc

## Appendix H. Wrapping C Libraries with gmmproc

gtkmm uses the gmmproc tool to generate most of its source code, using .defs files that define the APIs of `GObject`-based libraries. So it's quite easy to create additional gtkmm-style wrappers of other glib/GObject-based libraries.

This involves a variety of tools and some copying of existing build files, but it does at least work, and has been used successfully by several projects.

## The build structure

Generation of the source code for a gtkmm-style wrapper API requires use of tools such as gmmproc and `generate_wrap_init.pl`. In theory you could write your own build files to use these appropriately, but in practice it's usually easier to simply copy an existing project and modify it for your needs. Note however, that there is plenty of scope for improvement in the build structure that we use, so try to copy the latest version, and feel free to suggest improvements to make it more generic.

For instance, let's pretend that we are wrapping a C library called libexample. It provides a `GObject`-based API with types named, for instance, `ExampleThing` and `ExampleStuff`.

### Copying an existing project

Typically our wrapper library would be called libexamplemm. We can start by copying an existing *mm library, such as libgdamm, after checking it out from svn.

    $ svn co svn.gnome.org/svn/gnomemm/libgdamm/trunk libsomethingmm

This provides a directory structure for the source .hg and .ccg files and the generated .h and .cc files, with `Makefile.am` fragments that can specify the various files in use, in terms of generic `Makefile.am` variables. The directory structure usually looks like this, after we have renamed the directories appropriately:

- `libsomethingmm`: The top-level directory.

  - `libsomething`: Contains the main include file and the pkg-config .pc file.

    - `src`: Contains .hg and .ccg source files.

    - `libsomethingmm`: Contains generated and hand-written .h and .cc files.

      - `private`: Contains generated `*_p.h` files.

As well as renaming the directories, we should rename some of the source files. For instance:

    $ mv libsomething/libgdamm-2.0.pc.in libsomething/libsomethingmm-1.0.pc.in
    $ mv libsomething/libgdammconfig.h.in libsomething/libsomethingmmconfig.h.in
    $ mv libsomething/libgdamm.h libsomething/libsomethingmm.h
    $
    $ mv libsomething/src/libgda.defs libsomething/src/libsomething.defs
    $ mv libsomething/src/libgda_enums.defs libsomething/src/libsomething_enums.defs
    $ mv libsomething/src/libgda_methods.defs libsomething/src/libsomething_methods.defs
    $ mv libsomething/src/libgda_others.defs libsomething/src/libsomething_others.defs
    $ mv libsomething/src/libgda_signals.defs libsomething/src/libsomething_signals.defs
    $ mv libsomething/src/libgda_vfuncs.defs libsomething/src/libsomething_vfuncs.defs
    $ mv libsomething/src/libgda_docs.xml libsomething/src/libsomething_docs.xml
    $ mv libsomething/src/libgda_docs_override.xml libsomething/src/libsomething_docs_override.xml

A multiple-file renaming tool, such as prefixsuffix might help with this. We will provide the contents of these files later. In addition, if you started from an svn checkout, you'll probably want to get rid of all of the extra `.svn` directories in the source tree.

Note that files ending in `.in` will be used to generate files with the same name but without the `.in` suffix, by replacing some variables with actual values during the configure stage.

### Modifying build files

Now we edit the files to adapt them to to our needs. You might prefer to use a multiple-file search-replace too for this, such as regexxer.

#### autogen.sh

For instance, in `autogen.sh`:

- `PKG_NAME` must contain the new package name, such as libexamplemm.

- The test script lines must check for appropriate directory names, such as `$srcdir/libsomething/src`.

#### configure.in

In `configure.in` (or `configure.ac` in newer projects),

- The `AC_INIT()` line must mention a file in our library. We can edit this later if we don't yet know the names of any of the files that we will create.

- The `PACKAGE` variable must be changed to the correct name of the project, such as libsomethingmm.

- The version numbers should be reset to something small, such as 0.0.1. You may want to rename the version variables if they are not something generic. For instance, we would rename `LIBGDAMM_MAJOR_VERSION` to `LIBSOMETHINGMM_MAJOR_VERSION` or `LIBGENERICMM_MAJOR_VERSION`.

- The `AM_CONFIG_HEADER()` line must mention the correctly named config header file.

- The `PKG_CHECK_MODULES()` line must be modified to check for the correct dependencies. For instance, it might be changed to `PKG_CHECK_MODULES(LIBGENERICMM, gtkmm-2.4 >= 2.6.0 libsomething-1.0 >= 1.0.0).`

- The `AC_OUTPUT()` block must mention the correct directory names, as described above.

- The m4 script to generate doxygen input directory paths must mention the correct directory.

#### Makefile.am files

Next we must adapt the various `Makefile.am` files:

- The top-level `Makefile.am` must mention the correct child directory in the `SUBDIRS` variable.

- The `libexample/Makefile.am` must mention:

  - The correct child directories in the `SUBDIRS` variable.

  - The correct filenames in `EXTRA_DIST`.

  - The correct filenames in `*_includedir`, `*_include_HEADERS`, `*_configdir`, and `*_config_DATA`.

- In `libexample/libexamplemm/Makefile.am` we must mention the correct names in the generic variables that are used elsewhere in the build system:

  `sublib_name`

    The name of the library, such as libsomethingmm.

  `sublib_libname`

    The versioned name of the library, such as libsomethingmm-1.0

  `sublib_namespace`

    The name of the C++ namespace to use for this library, such as Something.

  `files_defs`

    The list of .defs and `*docs*.xml` files.

  `lib_LTLIBRARIES`

    This variable must mention the correct library name, and this library name must be used to form the `_SOURCES`, `_LDFLAGS`, and `_LIBADD` variable names.

- In `libexample/libexamplemm/private/Makefile.am`, `private_includedir` must contain the correct path.

- In `examples/Makefile.am_fragment`, `local_libgenericmm_lib` and `all_includes` must contain the correct paths.

- In `libexample/src/Makefile.am` we must set some more generic variables:

  `sublib_name`

    The name of the library, as in `libexample/libexamplemm/Makefile.am`.

  `sublib_namespace`

    The name of the C++ namespace, as in `libexample/libexamplemm/Makefile.am`

  `sublib_parentdir`

    The name of the directory containing the generated files, such as libexamplemm.

  `files_defs`

    The list of .defs and `*docs*.xml` files.

- In `build_shared/Makefile_gensrc.am_fragment`, you should remove the --namespace=Gnome option from the `gen_wrap_init_args` variable if your namespace will not be under the Gnome namespace. This should be the only place that you need to edit the generic `build_shared/` files.

#### Creating .hg and .ccg files

We should now create our first .hg and .ccg files, to wrap one of the objects in the C library. We will delete any existing .hg and .ccg files:

    $ rm -rf libexample/src/*.hg
    $ rm -rf libexample/src/*.ccg

and create new files:

    $ touch libexample/src/thing.hg
    $ touch libexample/src/thing.ccg

We must mention all of our .hg and .ccg files in the `libexample/src/Makefile_list_of_hg.am_fragment` file, in the `files_hg` variable.

Any extra non-generated .h and .cc source files may be placed in `libexample/libexamplemm/` and mentioned in `libexample/libexamplemm/Makefile.am`, in the `files_extra_h` and `files_extra_cc` variables.

In the .hg and .ccg files section you can learn about the syntax used in these files.

Installing and Using the svn version of gtkmm |  | Generating the .defs files.