Importing C++ / STL tutorial

BlitzMax Forums/BlitzMax Tutorials/Importing C++ / STL tutorial

skidracer(Posted 2007) [#1]
stlmap.bmx
========
This project implements a TIntMap object which you can use to store BlitzMax objects using integer keys. The code utilizes a second c++ file to do the hard work.

If you are new to C/C++ programming, there is a difference! Files ending with .c are c programs which are extremely easy to link to from BlitzMax. C++ programs use the .cpp suffix and require a few more skills when imported into blitzmax files.

' stlmap.bmx

' example of utilizing c++ stl from blitzmax

Import "stlmap.cpp"

Extern "C"
Function intmap_create%()
Function intmap_set%(intmap%,key%,value:Object)
Function intmap_get:Object(intmap%,key%)
End Extern

Type TIntMap

	Field intmap

	Method New()
		intmap=intmap_create()
	End Method
	
	Method Set(key:Int,value:Object)
		intmap_set(intmap,key,value)
	End Method

	Method Get:Object(key:Int)
		Return intmap_get(intmap,key)
	End Method

End Type

Local imap:TIntMap

imap=New TIntMap
imap.Set(3,"Three")
imap.Set(5,"Five")
imap.Set(8,"Eight")

For i=1 To 5000
	l$=String(imap.Get(Rand(10)))
	If l<>Null Print "l="+l
Next

Print "Done"

The import command references the following file which should be created with the specified name in the same folder as the intmap.bmx.

The Extern "C" block lists the C style interfaces to the c++ functions we implement below. Unfortunately BlitzMax is not capable of interfacing with c++ objects at a class level (with the exception of com style iunknown interfaces). This may change in future but for now C++ code will usually require some "C" exported declarations in order for it to be usable from BlitzMax.

// stlmap.cpp

// example of utilizing c++ stl from blitzmax

#include <set>
#include <map>
#include <list>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>

// this stuff would normally going in separate .h file...

#include <brl.mod/blitz.mod/blitz.h>

extern "C"{
	void *intmap_create();
	void intmap_set(void*stlmap,int key,BBObject*value);
	BBObject *intmap_get(void *stlmap,int key);
}

// and now the the code...

using namespace std;

typedef map<int,BBObject*> intmap;

void *intmap_create(){
	return new intmap();
}

void intmap_set(void*stlmap,int key,BBObject*value){
	intmap *imap;
	BBObject *obj;

	imap=(intmap*)stlmap;
//release old value
	obj=(*imap)[key];
	if (obj) bbObjectRelease(obj);
// retain new value if not null
	if (value==&bbNullObject)
		value=0;
	else
		bbObjectRetain(value);
// and set...
	(*imap)[key]=value;
}

BBObject *intmap_get(void *stlmap,int key){
	intmap *imap;
	BBObject *obj;
	imap=(intmap*)stlmap;
//release old value
	obj=(*imap)[key];
	if (!obj) obj=&bbNullObject;
	return obj;
}


A few things to note about the c++ code is the use of the blitz.h header file from the brl.blitz module. Blitzmax helpfully adds $blitzmax/mod as a default path whenever compiling C/C++ so the blitz.h file doesnt require an absolute path, making the project nice and portable.

This blitz.h file enables us to behave nicely with Blitz objects passed into the code with the above illustrating the use of the bbObjectRetain, bbObjectRelease and bbNullObject which are actually defined in blitz_object.h which is included along with a bunch of other very interesting headers by the blitz.h file.

The extern "C" block is where the C style interface is defined that matches the Export "C" block of the bmx file. If a c++ function is not declared prior to definition as extern "C" it will suffer from a name mangling process that makes it difficult to locate from blitzmax and will not on some compilers use the stdcall calling convention resulting in possibly erroneous behavior.

Exercises for the reader:

Implement a clear method to wipe the map and dereference all the bbObjects referenced.

Implement a count method that returns the number of items in the map.

Implement a method for enumerating either keys or values in the tree.


Torrente(Posted 2007) [#2]
Hey, thanks for the tutorial, this helps me out with a few things.
Quick question, though: If I wanted to use SuperStrict for the blitzmax code, what would I specify "Field intmap" as?


Azathoth(Posted 2007) [#3]
Variables are Int by default.


Brucey(Posted 2007) [#4]
Nice guide, Skid.

I guess it helps when you know what you are going ;-)


Chris C(Posted 2007) [#5]
How about adding some stuff about passing structs with libraries cause thats where people quite often become unstuck...


LAB[au](Posted 2007) [#6]
Yes a guide about structs would be nice. And how about QWord, Dword <-> Long, Int unsigned/signed mess?


H&K(Posted 2007) [#7]
Keep getting
Parse error Before string constant " @ line with extern in the .c file

This because Im using 2005Express?


skidracer(Posted 2007) [#8]
What .c file? This is a c++ tutorial. Also the import in the bmx file tells BlitzMax to compile the c++ file no visual studio required.


H&K(Posted 2007) [#9]
Well when you save a "cpp" file in express it doesnt save it as a cpp it saves it as a .cc, which Bmax wont reconise the file format of so what ive been doing is saveing them as .c

Do you think that thats all the problem is, the nameing of the extention?


H&K(Posted 2007) [#10]
Well, how stupid was that. Ok loaded it into notpad, and saved it as .cpp
Next question. If I only have the decleration files, and the definition files are precompiled .lib object file libaries, how do I tell Bmax the the Deifinitions are there?


skidracer(Posted 2007) [#11]
That would be outside the scope of this tutorial which is aimed at people wanting to compile their own c++ routines into their blitzmax applications using gcc/blitzmax.


H&K(Posted 2007) [#12]
Ok. Oh hum.


Brucey(Posted 2007) [#13]
Just to link in answer H&K's question (in case anyone else wonders about def files and libs)

http://blitzmax.com/Community/posts.php?topic=67804#757346