Writing TAPS using C++
This guide assumes that you have a working Unix/Cygwin installation and that you have been able to compile 'C' TAPs.
Getting a C++ toolchain built
Download tap_toolchain-1.1.tar.gz from
http://developer.berlios.de/project/showfiles.php?group_id=4128 . This needs to be unpacked into a folder. Normally the only steps needed are to create a folder /usr/local/topfield-gcc (writeable by you) and running make. You can look at the Readme extracted from the toolchain source for more instructions. In order to get a c++ compiler you need to change 2 instances of --enable-languages=c to --enable-languages=c,c++ in the top level makefile, then run make.
If you're feeling adventurous, you can disable the annoying warning about '#pragma once' being deprecated by editing gcc-2.95.2/gcc/cccp.c and commenting out the following lines
if (!instack[indepth].system_header_p)
warning ("`#pragma once' is obsolete");
I happen to like #pragma once as it appeals to the laziness in me :-)
Fixing libtap.a
The libtap.a shipped by topfield in the TAP development pack, and downloaded from many other sites contains an implementation of void* operator new(size_t size) which is apparently broken, along with no matching implementation for void operator delete(void* ptr). Nice. In order to avoid the hassle of defining operator new/delete on a per-class basis it's important to get rid of this definition of operator new so that the (working) one defined in
libc++utils.a can be used. Here's how
- copy libtap.a to another location. Keep a backup copy too.
- extract the contents using 'ar x libtap.a' - this should extract init.o
- run 'mips-objcopy -N __builtin_new init.o' - this removes the symbol __builtin_new from init.o
- re-create the archive - rm libtap.a; ar q libtap.a init.o
- replace the original libtap.a with your newly fixed one
Compiler Options
Make sure that you have -fno-weak in your c++ compiler options, in addition to those specified for C compilation. Without this the address resolution of functions with weak linkage can be double counted, leading to a crash.
What Works
- Classes, Inheritance
- Virtual Functions, but you must make sure that the vtables get fixed up - this requires a makefile step and initialization in code before any virtual functions are called. See the code for libframework? and it's example project.
- Stack and Heap allocation for classes
- C++ Syntax (declare variables away from beginning of scope, default parameters)
- Templates (but not with virtual member functions)
What Should Work
What Doesn't Work
- Pointers to non-static member functions
- Template classes with virtual functions
- initialization of static intances of objects - the memory is set to zero, but no ctor/dtor called on tap load/exit