Ok, I had some wonderful help over at the Cplusplus-sig mailing list and it turns out my problem was quite simple to solve(read type).
First, when you create a set of wrappers you need to append them to the init tab. The BOOST_PYTHON_MODULE macro will create you the function needed to append all of the wrappers to the init tab. The name of this function is init[module_name]. Thus invoking BOOST_PYTHON_MODULE(game) creates the routine initgame.
Second, you need to import the module you created after you initialize the python runtime. Also of note, the wrappers created in BOOST_PYTHON_MODULE will generate to/from python converters for all primitive and stl types (I think) so there's no need to define them again like I did.
Here is the corrected code. Please note that the python object foo is a copy, not a reference:
Code: Select all
#include <boost/python.hpp>
#include <string>
struct Unit
{
int health;
std::string name;
std::string type;
std::pair<int,int> coord;
};
BOOST_PYTHON_MODULE(game)
{
boost::python::class_<Unit>("Unit")
.def_readwrite("health", &Unit::health)
.def_readwrite("name", &Unit::name)
.def_readwrite("type", &Unit::type)
.def_readwrite("coord", &Unit::coord)
;
}
int main(int argc, char** argv)
{
PyImport_AppendInittab("game", &initgame);
Py_Initialize();
boost::python::object module = boost::python::import("game");
Unit unit1;
unit1.health = 100;
unit1.name = "Tank";
unit1.type = "Armor";
boost::python::object foo(unit1); // this is a python object that has copied the contents of unit1 (not a reference)
return 0;
}
Ok, that's great! We can convert a C++ object to a python object. However, this was not entirely what I wanted to do so anyone reading this gets some extra fun bonus information

As stated in my first post I wanted to pass C++ objects to a python function that modifies their values. This is my python function:
This code would call that python function hit:
Code: Select all
int main(int argc, char** argv)
{
PyImport_AppendInittab("game", &initgame);
Py_Initialize();
boost::python::object module = boost::python::import("game");
Unit unit1;
unit1.health = 100;
unit1.name = "Tank";
unit1.type = "Armor";
try{
boost::python::object hit = boost::python::import("pyfile").attr("hit"); // gets the hit function from my python file pyfile.py
boost::python::object ret = hit(unit1);
}
catch(...){
PyErr_Print();
}
std::cout << "unit1: " << unit1.health << ", " << unit1.name << ", " << unit1.type << std::endl;
return 0;
}
And this code prints out:
Wait... The health should be 90 now. What happened?
When you call the python function hit, it implicitly converts all of the arguments into python objects by copying the data. Thus unit1's data is copied into a boost::python object and this copy is used in the hit function. The hit function goes out of scope and the copy is garbage collected. The original is never modified.
Ok, so not what I want. What I want is easily achieved using boost ref. So if we look at that try catch block again:
Code: Select all
try{
boost::python::object hit = boost::python::import("pyfile").attr("hit");
boost::python::object ret = hit(boost::ref(unit1)); // this time with boost::ref giving us our desired outcome
}
catch(...){
PyErr_Print();
}
The output of the program is now:
Hooray! You made it to the end. I just started using Boost::Python so there's probably a few errors in what I said above. Also, a note about compiling.
Visual Studios: Don't forget to put -DBOOST_PYTHON_STATIC_LIB into your command line options (configuration properties)
Linux: Compile with -I/usr/include/python2.6 -lpython2.6 -lboost_python
Also also, I never got it running on Windows, but the Py++ is an awesome code generator for boost::python. The boost-ogre guys used it in their project.