Next: , Up: Module Creation


5.2.1 Compiling module sources

A typical chpsim-module source file (C++) is organized as follows:

     // "chptest.hac"
     // include headers
     #include <sim/chpsim/chpsim_dlfunction.h>
     
     // using declarations
     USING_CHPSIM_DLFUNCTION_PROLOGUE
     
     // function definitions
     static
     void
     my_alert(void) {
       // your code here
     }
     
     // a module export macro
     CHP_DLFUNCTION_LOAD_DEFAULT("alert_me", my_alert)
     
     static
     int_value_type
     compute(const int_value_type a, const int_value_type b) {
       // return some function of a and b
     }
     
     CHP_DLFUNCTION_LOAD_DEFAULT("twiddle", compute)

The header sim/chpsim/chpsim_dlfunction.h should have been installed in the pkgincludedir, $(prefix)/include/hackt/. This header defines the macros and prototypes used in the rest of the source. To add the header path to the search paths during compilation (actually, preprocessing), either pass the path directly ‘-I pkgincludedir’, or pass it indirectly using shell expansion and hackt-config: ‘-I `hackt-config --cflags`’. The latter method is preferred because it works across hosts with tools installed in different paths. The hackt-lt.mk template Makefile appends this flag to CPPFLAGS for you automatically, when compiling chpsim module objects.

— Macro: USING_CHPSIM_DLFUNCTION_PROLOGUE

This just imports certain type names from the header into the current namespace with C++ using-directives. The details are not important. For compatibility, one should always use this macro and let the preprocessor expand its definition.

— Macro: CHP_DLFUNCTION_LOAD_DEFAULT name sym

This is the macro that is responsible for binding the library symbol sym to a name of the user's choice name, a string. Name binding occurs automatically as soon as the module is loaded (by dlopen). (If you must know, this is achieved through static object initialization.) The C++ function symbol sym must be a prototype that uses the restricted set of types: int_value_type and such.

— Macro: REGISTER_DLFUNCTION_RAW name sym

This macro is responsible for binding the library symbol sym to a name of the user's choice name, a string. The function prototype of sym must be of the form: ‘chp_function_return_type (*) (const chp_function_argument_list_type&)’.

— Data type: chp_function_return_type

This is the return type used in chpsim's run-time environment. This is a memory-managed pointer (reference-counted) to an abstract expression type. Defined in Object/expr/dlfunction_fwd.h.

— Data type: chp_function_argument_list_type

This is the argument list type passed to all registered CHP functions. From this list-type, arguments are automatically extracted and passed to native C++ functions by CHP_DLFUNCTION_LOAD_DEFAULT. This is typically a list of memory-managed pointers to abstract expression types. Defined in Object/expr/dlfunction_fwd.h.

You may have noticed that the ‘compute’ function references return types and argument type int_value_type. A few such types are defined in the interface to chpsim's run-time. These types are defined in the header Object/expr/types.h.

— Data type: int_value_type

The signed integer data type, corresponding to ‘int<W>’ in CHP, typically defined to the host machine's native integer type.

— Data type: bool_value_type

The boolean data type, corresponding to ‘bool’ in CHP, typically defined to a C++ bool, or the smallest character type.

— Data type: real_value_type

The floating-point data type, corresponding to ‘real’ in CHP, typically defined to float or double.

— Data type: string_value_type

The string data type, typically defined to a C++ std::string. Recommendation: When defining functions that take this type as an argument, pass it by reference, for example: ‘void dump_string(const string_value_type&);’.

All functions that are registered with CHP_DLFUNCTION_LOAD_DEFAULT() are required to use only the above types in argument types and return types (and void). If your function uses different but convertible types, then write a call-wrapper that uses only the allowed types and forwards the arguments and return values. This is necessary when compiling and linking against symbols that belong to libraries beyond your control, or when you simply don't want to alter an existing library. When in doubt, it is always safe to use a such a wrapper. It is possible to change these types (say, to increase precision) if the entire suite of HACKT tools is re-compiled.

Compiling the source file for a shared library requires some additional measures. Fortunately, with the aid of conveniently installed template Makefiles, the complexities are hidden1. hackt-lt.mk provides a suffix rule for compiling C++ files ending with .cc to Libtool-wrapped object files .lo.

For every C++ source file (.cc) that is to be linked into the chpsim module, its corresponding object file should be referenced with the .lo extension (for Libtool object). The next section describes how to correctly link a chpsim module.


Footnotes

[1] Such complexities include additional compiler flags for shared-library objects, such as PIC (position-independent-code).