How to import external libraries to CINT Because of Cint limitation, special technique is needed to import arbitrary C/C++ libraries into Cint. Assuming you already have basic knowledge about cint/makecint, this document describes how to import external libraries using makecint. Rootcint is a version of makecint which is specialized for ROOT framework. This document does not focus on use of rootcint. But basic technique explained here will be applicable to rootcint too. Rootcint is different from makecint in following aspects. - Rootcint knows classes and environments of ROOT framework. - provides object persistence by automatically generated Streamer() ############################################################################ # Assumptions ############################################################################ Here are assumptions in this document. - A user have useful C/C++ library which he/she wants to use in the interpreter. - The library is provided by either source code, object file, static library or shared library. Let's call it 'extlib.cxx' , 'extlib.o' , 'extlib.a' or 'extlib.so'. - The library provides header file. Let's call it 'extlib.h'. - The user knows interface to the library he/she wants to use. ############################################################################ # First, you could try this... ############################################################################ If you the header file extlib.h is simple enough, you could simply feed extlib.h to makecint. If extlib.cxx is provided, $ makecint -mk makefile -dl extlib.dll -H extlib.h -C++ extlib.cxx $ make -f makefile If extlib.o , extlib.a or extlib.so is provided. $ makecint -mk makefile -dl extlib.dll -H extlib.h -l extlib.a $ make -f makefile If macro function is used in extlib.h, you will find problems. You can try using preprocessor by adding '-p' option. If extlib.cxx is provided, $ makecint -mk makefile -dl extlib.dll -p -H extlib.h -C++ extlib.cxx $ make -f makefile If extlib.o , extlib.a or extlib.so is provided. $ makecint -mk makefile -dl extlib.dll -p -H extlib.h -l extlib.a $ make -f makefile ############################################################################ # Using preprocessor might help... ############################################################################ Unfortunately, above works only if you are very lucky. Many of the library headers include something cint can not understand. Typical reasons are - Parsing limitation of Cint Cint is improved over the years. This case is decreasing, however, still not perfect. You can request improvements to the author. - Non-standard symbols are used in the library For portability reason, Cint only supports what is defined in ANSI C and ANSI/ISO C++, or at least subset of it. Anything out of this standard may not be understood by Cint. Please proceed to following sections if you find many errors. According to your situation, you can select Workaround 1 or 2. Workaround 1: Creating dummy header - You can not or do not want to modify the original header file. - Library is not under your control. It may be modified by other person without notice. - There are too many errors and it looks unrealistic to start from the original header file. Workaround 2: Modifying library header file - You can modify the original header file. - You are the originator of the library. You have 100% control of it. - You find simple errors only. ############################################################################ # Workaround 1: Creating dummy header ############################################################################ In many cases, original header file includes things that cint can not understand. This is not only because of cint limitation, but also by compiler specific keywords and non-standard symbols. There is very little hope to modify the original header. Besides, you want to keep the original library unchanged for maintenance reason. As a workaround, you need to create a dummy header which describes interface of the external library. Let's name it 'extlibdmy.h' in this document. 1. Dummy header overview A dummy header must consists of 2 parts. (1) Part where C/C++ compiler reads (2) Part where cint/makecint compiler reads These are segmented by '#ifdef __MAKECINT__' //////////////////////////////////////////////////// // extlibdmy.h //////////////////////////////////////////////////// #ifndef EXTLIB #define EXTLIB #ifndef __MAKECINT__ ^ | // Include extlib's original header file here. (1) | // This part is only read by C++ compiler. | #include "extlib.h" v #else // __MAKECINT__ ^ | // Declare interface to the external library. | // This part is read by cint/makecint only and (2) | // must be described within cint limitation. | // #pragma link statements can be added as option. | class ExtLib { ... }; | #pragma link C++ class ExtLib; v #endif // __MAKECINT__ #endif // EXTLIB //////////////////////////////////////////////////// Then do $ makecint -mk makefile -dl extlib.dll -H extlibdmy.h -C++ extlib.cxx $ make -f makefile or $ makecint -mk makefile -dl extlib.dll -H extlibdmy.h -l extlib.a $ make -f makefile NOTE: If the library defines many symbols, creation of part (2) may require significant amount of work. There will be criticism for recommending this method. But in my past experience, this is the best practice. Many of the library headers refer to non-standard symbols. Even if we remove cint limitations, having one such non-standard symbol becomes a bottleneck. Creating dummy header is an inevitable choice in order to avoid it. # How to describe dummy header This section explains how to describe the dummy header. - class You only need to describe public interface of the class and only what you want to access from the interpreter. For example, if original header extlib.h looks like below. //////////////////////////////////////////////////// // extlib.h //////////////////////////////////////////////////// class _DLLEXPORT ExtLib : _PUBLIC _BASEPROPRIETARY { public: // public interface typedef int ExtLibLocalType; ExtLib() ; ExtLib(const ExtLib& x); ~ExtLib() ; void publicMethod1(); int publicMethod2(const ExtLib& x); const ExtLib& publicMethod3() const; // public but suppose you do not need to use following // methods from the interpreter void publicMethod5(); int publicMethod6(const ExtLib& x); const ExtLib& publicMethod7() const; private: void privateMethod5(); const char* privateMethod6(const char* x); double privateMethod7() const; char* x; }; ////////////////////////////////////////////////////////// In extlibdmy.h , you only describe as follows. //////////////////////////////////////////////////// // extlibdmy.h //////////////////////////////////////////////////// #ifndef EXTLIB #define EXTLIB #ifndef __MAKECINT__ ^ | // Include extlib's original header file here. (1) | // This part is only read by C++ compiler. | #include "extlib.h" v #else // __MAKECINT__ ^ | // Declare interface to the external library. | // This part is read by cint/makecint only and (2) | // must be described within cint limitation. | // #pragma link statements can be added as option. | class ExtLib { | public: | // describe only things that you want to use from the | // interpreter | typedef int ExtLibLocalType; | ExtLib() ; | ExtLib(const ExtLib& x); | ~ExtLib() ; | | void publicMethod1(); | int publicMethod2(const ExtLib& x); | const ExtLib& publicMethod3() const; | }; v #endif // __MAKECINT__ #endif // EXTLIB //////////////////////////////////////////////////// - macro defined as scalar or string constant Macro that represents scalar or string constant can be described as is. For example. //////////////////////////////////////////////////// // extlibdmy.h //////////////////////////////////////////////////// #ifndef EXTLIB #define EXTLIB #ifndef __MAKECINT__ ^ | // Include extlib's original header file here. (1) | // This part is only read by C++ compiler. | #include "extlib.h" v #else // __MAKECINT__ ^ | // Declare interface to the external library. | // This part is read by cint/makecint only and (2) | // must be described within cint limitation. | // #pragma link statements can be added as option. | #define PI 3.141592 | #define LIBVERSION 20000214 | #define LIBNAME "My External Lib" v #endif // __MAKECINT__ #endif // EXTLIB //////////////////////////////////////////////////// - macro function Macro function needs special care. Cint can not pass arguments to macro function becuase there is no type information. You have to translate it to ANSI C style header. You also need to provide #pragma link information that it is a macro not a true function. Otherwise, Cint tries to get pointer to the function which causes compilation error. //////////////////////////////////////////////////// // extlib.h //////////////////////////////////////////////////// #define MAX(a,b) (a>b?a:b) #define MIX(a,b) (a>b?a:b) ////////////////////////////////////////////////////////// In extlibdmy.h , you describe as follows. //////////////////////////////////////////////////// // extlibdmy.h //////////////////////////////////////////////////// #ifndef EXTLIB #define EXTLIB #ifndef __MAKECINT__ ^ | // Include extlib's original header file here. (1) | // This part is only read by C++ compiler. | #include "extlib.h" v #else // __MAKECINT__ ^ | // Declare interface to the external library. | // This part is read by cint/makecint only and (2) | // must be described within cint limitation. | // #pragma link statements can be added as option. | double MAX(double a,double b); | double MIN(double a,double b); | int MAX(int a,int b); | int MIN(int a,int b); | | #pragma link MACRO MAX; | #pragma link MACRO MIN; v #endif // __MAKECINT__ #endif // EXTLIB //////////////////////////////////////////////////// - pointer to function It is recommended to use typedef for pointer to function. Cint can process basic pointer to function syntax, however, there can be bugs. Typedef will prevent such bug. - template Cint/makecint can not precompile template itself. It can only precompile instantiated template class or function. Cint can not process partial template specialization. Such description must be avoided in the dummy header. //////////////////////////////////////////////////// // extlibdmy.h //////////////////////////////////////////////////// #ifndef EXTLIB #define EXTLIB #ifndef __MAKECINT__ ^ | // Include extlib's original header file here. (1) | // This part is only read by C++ compiler. | #include "extlib.h" v #else // __MAKECINT__ ^ | // Declare interface to the external library. | // This part is read by cint/makecint only and (2) | // must be described within cint limitation. | // #pragma link statements can be added as option. | template<class T> ExtLibArray { | ... | }; | // instantiate template class | #pragma link C++ class ExtLibArray<int>; | #pragma link C++ class ExtLibArray<TExtLiba>; | | template<class T> void ExtLibTmpltFunc(T a) { ... } | // instantiate template function | void ExtLibTmpltFunc(int a); | void ExtLibTmpltFunc(TExtLibA a); | #pragma link C++ function ExtLibTmpltFunc; // optional v #endif // __MAKECINT__ #endif // EXTLIB //////////////////////////////////////////////////// - STL STL is a template library. So basically you need to follow above rule. On top of it, you need to give '-cint -M0x10' option to makecint. STL allocator overrides operator new/delete. This conflicts with Cint's operator new/delete. You need to give '-cint -M0x10' option to avoid this. HP-UX needs '-cint -M0x1c'. $ makecint -mk makefile -dl extlib.dll -H extlibdmy.h -C++ extlib.cxx -cint -M0x10 $ make -f makefile or $ makecint -mk makefile -dl extlib.dll -H extlibdmy.h -l extlib.a -cint -M0x10 $ make -f makefile - exception Cint can parse exception syntax and ignores it. It should be fine to leave exception specification in the dummy header. If you find problem , please eliminate exception specification from the dummy header. - global function, global variable, typedef, etc... Most of the other C++ language constructs can be processed by cint/makecint. You can copy the original description in original header file as it is. - other tips, For other cint limitations, please refer to doc/limitati.txt ############################################################################ # Workaround 2: Modifying the original header ############################################################################ Basic rule is the same as Workaround 1. You will do it for the original header file instead of dummy header. This method is recommended only if you have 100% control of the library.