Supported Platforms
CABLE generates C++ code that is to be built by your compiler. This has
several implications on platform support:
- Generated code cannot have errors according to your
compiler. Although CABLE generates valid C++ code, not
all compilers accept all valid C++ code.
- Generated code is very specific to the real types of every
function argument and return type. If any are library defined
types, then they must match the types in the library provided by
your compiler. Since GCC-XML is used to parse the classes to be
wrapped, and therefore the libraries provided by the compiler,
CABLE can only support compilers supported by GCC-XML.
Currently, the supported platforms are:
- GCC 3.2.x, 3.1.x, 3.0.x, and 2.95.x on UNIX and Cygwin
- MIPSpro 7.3 on IRIX
- Visual C++ 7.0 (MSDev.NET) on Windows
- Visual C++ 6.0, service pack 5 on Windows
- Intel C++ 5.0 within Visual C++ 6.0 on Windows
Currently, the supported interpreted languages are:
Running CABLE
In general, there are four steps to produce wrappers with CABLE.
- Write the CABLE configuration file.
- Run
cable to generate wrappers.
- Compile the generated code.
- Link the wrappers into a package.
Writing the CABLE Configuration File
The CABLE configuration file is written in C++. Here is the
basic layout:
// Define your classes or include headers.
#ifdef CABLE_CONFIGURATION
namespace _cable_
{
const char* const group="MyGroup1";
const char* const package="MyPackage";
const char* const groups[]={"MyGroup1"};
namespace wrappers
{
// List class wrappers as typedefs.
// Name of typedef will be wrapped name.
}
}
// Additional code to ensure implicit instantiation of
// class templates that are to be wrapped.
#endif
The beginning of the configuration file must provide the code
defining the C++ classes to be wrapped. The generated code will
acutally
#include the configuration file, but will
not define
CABLE_CONFIGURATION. Therefore, all
CABLE-related code should be placed inside the configuration
section. This approach allows one to define a class and wrap it
all in a single file.
Cable configuration code is placed in the _cable_
namespace. This avoids name conflicts with classes getting
wrapped.
The group setting must be initialized by a string
literal, and must be a valid C-identifier. It names the set of
wrappers defined in this particular configuration file.
The package setting must be initialized by a string
literal, and must be a valid C-identifier. It gives the name of
the package of wrappers to be generated.
The groups setting must be initialized by an array of
string literals. They name the set of groups to be combined into
this package of wrappers. When the package is built, code
generated from all the groups listed here (each with its own
configuration) should be compiled and linked together.
Wrappers produced from several configuration files can be combined
into a single package. Each group's configuration file needs only
know the name of the group. Only a single master package
configuration file needs the package and
groups settings. This file may or may not contain
any class wrappers. The generated code will contain package-level
initialization code for all the groups in the package.
The _cable_::wrappers namespace should contain a list
of typedefs for the classes to be wrapped. For example,
typedef ::Foo Foo;
typedef ::Bar<int> Bar_int;
will produce class wrappers called "
Foo" (wrapping class
Foo), and "
Bar_int" (wrapping class template
instantiation
Bar<int>). Nested namespaces are
allowed, and the names will be used in the generated language.
For example,
namespace zot { typedef ::Foo Foo; }
will produced a class wrapper called "
zot::Foo".
The actual format of the "
zot::" prefix is dependent
on the target language.
Finally, after the _cable_ namespace has been closed,
one must write code to force implicit instantiations of class
templates. This is necessary to get GCC-XML to dump proper
descriptions of class template instantiations. For the above
example, we can use this code to make sure that
Bar<int> is properly instantiated:
void force_instantiation()
{
sizeof(Bar<int>);
}
See the
Examples page for a complete
configuration file.
Running cable to Generate Wrappers
CABLE is run as a command-line executable called "
cable".
Here is its basic usage:
cable config.cxx <language-name> output.cxx [options]
Cable will internally run GCC-XML on the input configuration file
and parse the result. Any preprocessor options (like
-I or
-D) that are given to cable will
automatically be passed on to GCC-XML. If the
gccxml
executable is not in your path, you can set
CABLE_GCCXML in your environment to point at it.
Alternatively, you can specify the executable's location with the
--gccxml option.
The language name should specify the language for the generated
wrappers. Currently, only Tcl is supported. It is specified by
the "-tcl" option. The output file name must
immediately follow the language name because future versions of
CABLE may allow generation of wrappers for more than one language
at a time.
Compiling the Generated Wrappers
The generated output file should be compiled by the same compiler
that GCC-XML is configured to simulate. Building the generated
code requires that the include path contain the CABLE include-file
directory. This will be in one of these places:
- If CABLE is running from its build tree, use the top-level
CABLE source diretory.
- If CABLE is running from an installation directory, use
PREFIX/include/Cable. This is valid
only on UNIX platforms.
Linking Wrappers into a Library
Once all the wrappers in the package have been compiled, they
should be linked into a library. The package should link to the
CABLE facility library for the corresponding language. Currently,
this is always the "
CableTclFacility" library since
only Tcl wrapping is supported.