reist Posted February 24, 2006 Report Share Posted February 24, 2006 (edited) I exposed a big piece of Item/Inventory hirarchy plus other parts of code to python and here's a summary of what I learned about how it's supposed to be done: Virtual functions are accepted as easily as non-virtual. Just write the regular .def() and it'll do. It only gets complicated if we want to derive new classes from that class and override the virtual functions. The boost::python documentation explains what to do in such a case perfectly. For pure virtual functions, the class only has to be defined as having no constructor and as non-copyable:class_<AbstractClass, boost::noncopyable>("AbstractClass", no_init) If there are overloaded functions, they have to be passed as different function pointers. No way around it. For example: void (Item::*f1)(InventoryBase&) = &Item::insert; void (Item::*f2)(InventoryTroop&) = &Item::insert; void (Item::*f3)(InventoryCraft&) = &Item::insert; class_<Item, boost::noncopyable>("Item", no_init) .def("insert", f1) .def("insert", f2) .def("insert", f3) Don't create functions that take iterators that would need to be exposed! It's normally impossible to pass an iterator from python to C++. In the other direction it's quite possible, as a pair of iterators to the start and end of a range (that's how iterators work in python).By the way, it is possible to expose sequences (vector, list, deque...) and maps to python 100%. There are special (and very complex) templates in boost::python that let you do that. They don't work on multimaps! BUT, as we don't use stl collections directly, we can only get limited usage in C++ and even more limited in python.This is how it's possible to create an iterator over the whole collection inside a class that works in both C++ and python:The class: class CollectionWrapper { public: typedef SomeCollection<SomeType> Col; typedef Col::iterator iterator; // needed by iterator<>() iterator begin() {return col.begin(); } iterator end() {return col.end(); } private: Col col; }; The _py.cpp file: class_<CollectionWrapper>("CollectionWrapper") .def("__iter__", iterator<CollectionWrapper>()) A note about map: for each class using a different underlying map, it's value_type has to be exposed too. For example:class_< std::pair<String const, RackPtr> >("TInventoryEntry") .def_readonly("first", &std::pair<String const, RackPtr>::first) .def_readwrite("second", &std::pair<String const, RackPtr>::second) ; Also, each shared_ptr that is passed to python has to be exposed too:Somewhere before: typedef TSharedPtr<Rack> RackPtr; In the _py.cpp file: register_ptr_to_python<RackPtr>(); Edited February 24, 2006 by reist Link to comment Share on other sites More sharing options...
rincewind Posted February 24, 2006 Report Share Posted February 24, 2006 Good job reist. Maybe put this in the wiki? Rincewind Link to comment Share on other sites More sharing options...
reist Posted February 24, 2006 Author Report Share Posted February 24, 2006 No problem. Here's the direct link:http://docs.projectxenocide.com/index.php/Code::ExposingCpp Link to comment Share on other sites More sharing options...
red knight Posted February 25, 2006 Report Share Posted February 25, 2006 Excelent work there reist. GreetingsRed Knight Link to comment Share on other sites More sharing options...
Recommended Posts