Adding Boost::Python wrapping

This commit is contained in:
Damien Dupuis 2011-05-10 14:25:49 +00:00
parent 80dd17bbef
commit d8e82643e6
4 changed files with 256 additions and 19 deletions

View File

@ -13,22 +13,22 @@ SET ( cpps Circuit.cpp
Subckt.cpp
Value.cpp
)
#SET ( pycpps PySpice.cpp
# )
SET ( pycpps PySpice.cpp
)
ADD_LIBRARY(spice ${cpps})
TARGET_LINK_LIBRARIES(spice)
SET_TARGET_PROPERTIES(spice PROPERTIES VERSION 1.0 SOVERSION 1)
INSTALL(TARGETS spice DESTINATION lib${LIB_SUFFIX} )
#IF(Boost_FOUND)
# ADD_LIBRARY(pySPICE MODULE ${pycpps})
# SET_TARGET_PROPERTIES(pySPICE PROPERTIES
# OUTPUT_NAME "SPICE"
# PREFIX ""
# )
# TARGET_LINK_LIBRARIES(pySPICE spice ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
# INSTALL(TARGETS pySPICE DESTINATION ${PYTHON_SITE_PACKAGES})
#ENDIF(Boost_FOUND)
IF(Boost_FOUND)
ADD_LIBRARY(pySPICE MODULE ${pycpps})
SET_TARGET_PROPERTIES(pySPICE PROPERTIES
OUTPUT_NAME "SPICE"
PREFIX ""
)
TARGET_LINK_LIBRARIES(pySPICE spice ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
INSTALL(TARGETS pySPICE DESTINATION ${PYTHON_SITE_PACKAGES})
ENDIF(Boost_FOUND)
INSTALL(FILES ${hpps} DESTINATION include/vlsisapd/spice)

View File

@ -0,0 +1,150 @@
using namespace std;
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
using namespace boost::python;
#include "vlsisapd/spice/Instances.h"
#include "vlsisapd/spice/Sources.h"
#include "vlsisapd/spice/Subckt.h"
#include "vlsisapd/spice/Circuit.h"
#include "vlsisapd/spice/SpiceException.h"
#include "vlsisapd/spice/PySTLMapWrapper.h"
namespace SPICE {
void translator(SpiceException const& e) {
PyErr_SetString(PyExc_UserWarning, e.what());
}
// for optional arguments
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(addLibrary_overloads, addLibrary, 1, 2);
BOOST_PYTHON_MODULE(SPICE) {
// vector and map wrapping for Spice::Instance
class_<std::vector<std::string> >("ConnectorsVector")
.def(vector_indexing_suite<std::vector<std::string> >())
;
STL_MAP_WRAPPING(std::string, std::string, "ParametersMap")
// class SPICE::Instance
class_<Instance, Instance*>("Instance", init<std::string, std::string>())
// accessors
.def("getName" , &Instance::getName )
.def("getModel" , &Instance::getModel )
.def("getParameterValue", &Instance::getParameterValue )
// modifiers
.def("addConnector", &Instance::addConnector )
.def("addParameter", &Instance::addParameter )
// stl containers
.def("getConnectors", &Instance::getConnectors, return_value_policy<copy_const_reference>())
.def("getParameters", &Instance::getParameters, return_value_policy<copy_const_reference>())
;
// class SPICE::Mosfet
class_<Mosfet, bases<Instance> >("Mosfet", init<std::string, std::string, std::string, std::string, std::string, std::string>())
// accessors
.def("getDrain" , &Mosfet::getDrain )
.def("getGrid" , &Mosfet::getGrid )
.def("getSource", &Mosfet::getSource )
.def("getBulk" , &Mosfet::getBulk )
;
// class SPICE::Capacitor
class_<Capacitor, bases<Instance> >("Capacitor", init<std::string, std::string, std::string, std::string>())
// accessors
.def("getPositive", &Capacitor::getPositive )
.def("getNegative", &Capacitor::getNegative )
.def("getValue" , &Capacitor::getValue )
;
// class SPICE::Resistor
class_<Resistor, bases<Instance> >("Resistor", init<std::string, std::string, std::string, std::string>())
// accessors
.def("getFirst" , &Resistor::getFirst )
.def("getSecond", &Resistor::getSecond )
.def("getValue" , &Resistor::getValue )
;
// class SPICE::Source !! abstract class !!
class_<Source, Source*, boost::noncopyable>("Source", no_init)
// accessors
.def("getName" , &Source::getName )
.def("getPositive", &Source::getPositive )
.def("getNegative", &Source::getNegative )
.def("getValue" , &Source::getValue )
;
// class SPICE::Voltage
class_<Voltage, bases<Source> >("Voltage", init<std::string, std::string, std::string, std::string>())
;
// class SPICE::Current
class_<Current, bases<Source> >("Current", init<std::string, std::string, std::string, std::string>())
;
// vector indexing for Spice::Subckt
// InterfacesVector = ConnectorsVector already exists
class_<std::vector<Instance*> >("InstancesVector")
.def(vector_indexing_suite<std::vector<Instance*>, true>())
;
// ParametersMap is already defined
// class SPICE::Subckt
class_<Subckt, Subckt*>("Subckt", init<std::string>())
// accessors
.def("getName", &Subckt::getName )
// modifiers
.def("addInterface", &Subckt::addInterface )
.def("addInstance" , &Subckt::addInstance )
.def("addParameter", &Subckt::addParameter )
// stl containers
.def("getInterfaces", &Subckt::getInterfaces, return_value_policy<copy_const_reference>())
.def("getInstances" , &Subckt::getInstances , return_value_policy<copy_const_reference>())
.def("getParameters", &Subckt::getParameters, return_value_policy<copy_const_reference>())
;
// vector indexing for Spice::Circuit
class_<std::vector<std::pair<std::string, std::string> > > ("LibrariesVector")
.def(vector_indexing_suite<std::vector<std::pair<std::string, std::string> > >())
;
// InstancesVector already exists
// ParametersMap = OptionsMap already exists
class_<std::vector<Source*> >("SourcesVector")
.def(vector_indexing_suite<std::vector<Source*> >())
;
class_<std::vector<Subckt*> >("SubcktsVector")
.def(vector_indexing_suite<std::vector<Subckt*> >())
;
// class SPICE::Circuit
class_<Circuit, Circuit*>("Circuit", init<>())
// properties
.add_property("title", &Circuit::getTitle, &Circuit::setTitle )
// modifiers
.def("addInclude" , &Circuit::addInclude )
.def("addLibrary" , &Circuit::addLibrary , addLibrary_overloads())
.def("addInstance" , &Circuit::addInstance )
.def("addSource" , &Circuit::addSource )
.def("addOption" , &Circuit::addOption )
.def("addParameter" , &Circuit::addParameter )
.def("addSubckt" , &Circuit::addSubckt , return_value_policy<reference_existing_object>())
// stl containers
.def("getIncludes" , &Circuit::getIncludes , return_value_policy<copy_const_reference>())
.def("getLibraries" , &Circuit::getLibraries , return_value_policy<copy_const_reference>())
.def("getOptions" , &Circuit::getOptions , return_value_policy<copy_const_reference>())
.def("getParameters", &Circuit::getParameters, return_value_policy<copy_const_reference>())
.def("getSubckts" , &Circuit::getSubckts , return_value_policy<copy_const_reference>())
.def("getInstances" , &Circuit::getInstances , return_value_policy<copy_const_reference>())
.def("getSources" , &Circuit::getSources , return_value_policy<copy_const_reference>())
// others
.def("readFromFile" , &Circuit::readFromFile , return_value_policy<reference_existing_object>())
.staticmethod("readFromFile")
.def("writeToFile" , &Circuit::writeToFile )
;
// SpiceException translator
register_exception_translator<SpiceException>(translator)
;
}
}

View File

@ -0,0 +1,87 @@
#include <map>
#include <boost/python.hpp>
namespace SPICE {
// since we want to wrap std::map<type, Class*> with cimple pointers (no boost::shared_ptr),
// we cannot use map_indexing_suite which has not the right return_value_policy.
// std::maps with no points value are wrapped using map_indexing_suite technique.
//
// This templated map_item struct is intended to be used for 'manual' wrapping:
template<class Key, class Val>
struct map_item {
typedef std::map<Key,Val> Map;
static Val get(Map & self, const Key idx) {
if (self.find(idx) == self.end()) {
PyErr_SetString(PyExc_KeyError,"Map key not found");
throw_error_already_set();
}
return self[idx];
}
static void set(Map& self, const Key idx, const Val val) { self[idx]=val; }
static void del(Map& self, const Key n) { self.erase(n); }
static bool in (Map const& self, const Key n) { return self.find(n) != self.end(); }
static list keys(Map const& self) {
list t;
for(typename Map::const_iterator it = self.begin() ; it!=self.end() ; ++it)
t.append(it->first);
return t;
}
static list values(Map const& self) {
list t;
for(typename Map::const_iterator it=self.begin(); it!=self.end(); ++it)
t.append(it->second);
return t;
}
static list items(Map const& self) {
list t;
for(typename Map::const_iterator it=self.begin(); it!=self.end(); ++it)
t.append( make_tuple(it->first, it->second) );
return t;
}
};
#define STL_MAP_WRAPPING_PTR(KEY_TYPE, VALUE_TYPE, PYTHON_TYPE_NAME) \
class_<std::pair<const KEY_TYPE, VALUE_TYPE> >((std::string(PYTHON_TYPE_NAME)+std::string("DATA")).c_str()) \
.def_readonly ("key" , &std::pair<const KEY_TYPE, VALUE_TYPE>::first ) \
.def_readwrite("value", &std::pair<const KEY_TYPE, VALUE_TYPE>::second) \
; \
class_<std::map<KEY_TYPE, VALUE_TYPE> >(PYTHON_TYPE_NAME) \
.def("__len__" , &std::map<KEY_TYPE, VALUE_TYPE>::size) \
.def("__iter__" , boost::python::iterator<std::map<KEY_TYPE, VALUE_TYPE>, return_internal_reference<> >()) \
.def("__getitem__" , &map_item<KEY_TYPE, VALUE_TYPE>().get, return_internal_reference<>()) \
.def("__setitem__" , &map_item<KEY_TYPE, VALUE_TYPE>().set ) \
.def("__delitem__" , &map_item<KEY_TYPE, VALUE_TYPE>().del ) \
.def("__contains__", &map_item<KEY_TYPE, VALUE_TYPE>().in ) \
.def("clear" , &std::map<KEY_TYPE, VALUE_TYPE>::clear ) \
.def("has_key" , &map_item<KEY_TYPE, VALUE_TYPE>().in ) \
.def("keys" , &map_item<KEY_TYPE, VALUE_TYPE>().keys ) \
.def("values" , &map_item<KEY_TYPE, VALUE_TYPE>().values) \
.def("items" , &map_item<KEY_TYPE, VALUE_TYPE>().items ) \
;
#define STL_MAP_WRAPPING(KEY_TYPE, VALUE_TYPE, PYTHON_TYPE_NAME) \
class_<std::pair<const KEY_TYPE, VALUE_TYPE> >((std::string(PYTHON_TYPE_NAME)+std::string("DATA")).c_str()) \
.def_readonly ("key" , &std::pair<const KEY_TYPE, VALUE_TYPE>::first ) \
.def_readwrite("value", &std::pair<const KEY_TYPE, VALUE_TYPE>::second) \
; \
class_<std::map<KEY_TYPE, VALUE_TYPE> >(PYTHON_TYPE_NAME) \
.def("__len__" , &std::map<KEY_TYPE, VALUE_TYPE>::size) \
.def("__iter__" , boost::python::iterator<std::map<KEY_TYPE, VALUE_TYPE>, return_internal_reference<> >()) \
.def("__getitem__" , &map_item<KEY_TYPE, VALUE_TYPE>().get ) \
.def("__setitem__" , &map_item<KEY_TYPE, VALUE_TYPE>().set ) \
.def("__delitem__" , &map_item<KEY_TYPE, VALUE_TYPE>().del ) \
.def("__contains__", &map_item<KEY_TYPE, VALUE_TYPE>().in ) \
.def("clear" , &std::map<KEY_TYPE, VALUE_TYPE>::clear ) \
.def("has_key" , &map_item<KEY_TYPE, VALUE_TYPE>().in ) \
.def("keys" , &map_item<KEY_TYPE, VALUE_TYPE>().keys ) \
.def("values" , &map_item<KEY_TYPE, VALUE_TYPE>().values) \
.def("items" , &map_item<KEY_TYPE, VALUE_TYPE>().items ) \
;
} // namespace

View File

@ -20,20 +20,20 @@ class Subckt {
Subckt(std::string name): _name(name), _interfaces(), _instances(), _parameters() {}
~Subckt() {}
inline std::string getName();
inline std::vector<std::string>& getInterfaces();
inline std::vector<Instance*>& getInstances();
inline std::map<std::string, std::string>& getParameters();
inline const std::string getName();
inline const std::vector<std::string>& getInterfaces();
inline const std::vector<Instance*>& getInstances();
inline const std::map<std::string, std::string>& getParameters();
inline void addInterface(std::string);
inline void addInstance (Instance*);
void addParameter(std::string, std::string);
};
inline std::string Subckt::getName() { return _name; }
inline std::vector<std::string>& Subckt::getInterfaces() { return _interfaces; }
inline std::vector<Instance*>& Subckt::getInstances() { return _instances; }
inline std::map<std::string, std::string>& Subckt::getParameters() { return _parameters; }
inline const std::string Subckt::getName() { return _name; }
inline const std::vector<std::string>& Subckt::getInterfaces() { return _interfaces; }
inline const std::vector<Instance*>& Subckt::getInstances() { return _instances; }
inline const std::map<std::string, std::string>& Subckt::getParameters() { return _parameters; }
inline void Subckt::addInterface(std::string name) { _interfaces.push_back(name); }
inline void Subckt::addInstance(Instance* inst) { _instances.push_back(inst); }