Minimize passing STL objects past dynamic library boundaries to improve stability of IfcOpenShell-Python

This commit is contained in:
Thomas Krijnen
2015-06-02 13:29:08 +00:00
parent 5a994ebe28
commit b96cf38e17
4 changed files with 138 additions and 32 deletions
@@ -43,9 +43,11 @@ class entity_instance(object):
def __init__(self, e): def __init__(self, e):
super(entity_instance, self).__setattr__('wrapped_data', e) super(entity_instance, self).__setattr__('wrapped_data', e)
def __getattr__(self, name): def __getattr__(self, name):
if name in self.wrapped_data.get_attribute_names(): INVALID, FORWARD, INVERSE = range(3)
attr_cat = self.wrapped_data.get_attribute_category(name)
if attr_cat == FORWARD:
return entity_instance.wrap_value(self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name))) return entity_instance.wrap_value(self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)))
elif name in self.wrapped_data.get_inverse_attribute_names(): elif attr_cat == INVERSE:
return entity_instance.wrap_value(self.wrapped_data.get_inverse(name)) return entity_instance.wrap_value(self.wrapped_data.get_inverse(name))
else: raise AttributeError("entity instance of type '%s' has no attribute '%s'"%(self.wrapped_data.is_a(), name)) else: raise AttributeError("entity instance of type '%s' has no attribute '%s'"%(self.wrapped_data.is_a(), name))
@staticmethod @staticmethod
+64 -6
View File
@@ -93,6 +93,47 @@
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, void*, int); %ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, void*, int);
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, std::istream&, int); %ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, std::istream&, int);
// Ignore the std::vector accessors and replace them to pairs that will
// be expanded to Python tuples by means of typemaps. This in order to
// minimize passing STL objects across dynamic library boundaries.
%ignore IfcGeom::Representation::Triangulation::verts;
%ignore IfcGeom::Representation::Triangulation::faces;
%ignore IfcGeom::Representation::Triangulation::edges;
%ignore IfcGeom::Representation::Triangulation::normals;
%ignore IfcGeom::Representation::Triangulation::material_ids;
%ignore IfcGeom::Representation::Triangulation::materials;
%extend IfcGeom::Representation::Triangulation {
std::pair<const int*, unsigned> get_faces() {
return std::make_pair(&$self->faces()[0], $self->faces().size());
}
std::pair<const int*, unsigned> get_edges() {
return std::make_pair(&$self->edges()[0], $self->edges().size());
}
std::pair<const int*, unsigned> get_material_ids() {
return std::make_pair(&$self->material_ids()[0], $self->material_ids().size());
}
std::pair<const IfcGeom::Material*, unsigned> get_materials() {
return std::make_pair(&$self->materials()[0], $self->materials().size());
}
}
%extend IfcGeom::Representation::Triangulation<float> {
std::pair<const float*, unsigned> get_verts() {
return std::make_pair(&$self->verts()[0], $self->verts().size());
}
std::pair<const float*, unsigned> get_normals() {
return std::make_pair(&$self->normals()[0], $self->normals().size());
}
}
%extend IfcGeom::Representation::Triangulation<double> {
std::pair<const double*, unsigned> get_verts() {
return std::make_pair(&$self->verts()[0], $self->verts().size());
}
std::pair<const double*, unsigned> get_normals() {
return std::make_pair(&$self->normals()[0], $self->normals().size());
}
}
%extend IfcGeom::IteratorSettings { %extend IfcGeom::IteratorSettings {
%pythoncode %{ %pythoncode %{
attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices") attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices")
@@ -118,12 +159,29 @@
if _newclass: if _newclass:
# Hide the getters with read-only property implementations # Hide the getters with read-only property implementations
id = property(id) id = property(id)
verts = property(verts) faces = property(get_faces)
faces = property(faces) edges = property(get_edges)
edges = property(edges) material_ids = property(get_material_ids)
normals = property(normals) materials = property(get_materials)
material_ids = property(material_ids) %}
materials = property(materials) };
// Specialized accessors follow later, for otherwise property definitions
// would appear before templated getter functions are defined.
%extend IfcGeom::Representation::Triangulation<float> {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
verts = property(get_verts)
normals = property(get_normals)
%}
};
%extend IfcGeom::Representation::Triangulation<double> {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
verts = property(get_verts)
normals = property(get_normals)
%} %}
}; };
+15 -2
View File
@@ -216,8 +216,8 @@ namespace IfcUtil {
std::ofstream f(fn.c_str()); std::ofstream f(fn.c_str());
f << (*$self); f << (*$self);
} }
std::vector<int> entity_names() const { std::vector<unsigned> entity_names() const {
std::vector<int> keys; std::vector<unsigned> keys;
keys.reserve(std::distance($self->begin(), $self->end())); keys.reserve(std::distance($self->begin(), $self->end()));
for (IfcParse::IfcFile::entity_by_id_t::const_iterator it = $self->begin(); it != $self->end(); ++ it) { for (IfcParse::IfcFile::entity_by_id_t::const_iterator it = $self->begin(); it != $self->end(); ++ it) {
keys.push_back(it->first); keys.push_back(it->first);
@@ -232,6 +232,19 @@ namespace IfcUtil {
} }
%extend IfcParse::IfcLateBoundEntity { %extend IfcParse::IfcLateBoundEntity {
int get_attribute_category(const std::string& name) const {
const std::vector<std::string> names = $self->getAttributeNames();
if (std::find(names.begin(), names.end(), name) != names.end()) {
return 1;
} else {
const std::vector<std::string> names = $self->getInverseAttributeNames();
if (std::find(names.begin(), names.end(), name) != names.end()) {
return 2;
} else {
return 0;
}
}
}
%pythoncode %{ %pythoncode %{
set_argument = lambda self,x,y: self._set_argument(x) if y is None else self._set_argument(x,y) set_argument = lambda self,x,y: self._set_argument(x) if y is None else self._set_argument(x,y)
%} %}
+41 -8
View File
@@ -41,13 +41,46 @@
#include "../ifcparse/IfcLateBoundEntity.h" #include "../ifcparse/IfcLateBoundEntity.h"
%} %}
// The following typemaps are an alternative for the read-only std::vector
// implementations provided by SWIG, as passing STL objects across dynamic
// library boundaries can be problematic.
%typemap(out) std::pair<const float*, unsigned> {
$result = PyTuple_New($1.second);
for (unsigned i = 0; i < $1.second; ++i) {
PyTuple_SetItem($result, i, PyFloat_FromDouble($1.first[i]));
}
}
%typemap(out) std::pair<const double*, unsigned> {
$result = PyTuple_New($1.second);
for (unsigned i = 0; i < $1.second; ++i) {
PyTuple_SetItem($result, i, PyFloat_FromDouble($1.first[i]));
}
}
%typemap(out) std::pair<const int*, unsigned> {
$result = PyTuple_New($1.second);
for (unsigned i = 0; i < $1.second; ++i) {
PyTuple_SetItem($result, i, PyLong_FromLong($1.first[i]));
}
}
%typemap(out) std::pair<const std::string*, unsigned> {
$result = PyTuple_New($1.second);
for (unsigned i = 0; i < $1.second; ++i) {
PyTuple_SetItem($result, i, PyUnicode_FromString($1.first[i]->c_str()));
}
}
%typemap(out) std::pair<const IfcGeom::Material*, unsigned> {
$result = PyTuple_New($1.second);
for (unsigned i = 0; i < $1.second; ++i) {
PyTuple_SetItem($result, i, SWIG_NewPointerObj(SWIG_as_voidptr(&$1.first[i]), SWIGTYPE_p_IfcGeom__Material, 0));
}
}
%typemap(out) std::vector<unsigned> {
$result = PyTuple_New($1.size());
unsigned i = 0;
for (std::vector<unsigned>::const_iterator it = $1.begin(); it != $1.end(); ++it) {
PyTuple_SetItem($result, i++, PyLong_FromLong(*it));
}
}
%include "IfcGeomWrapper.i" %include "IfcGeomWrapper.i"
%include "IfcParseWrapper.i" %include "IfcParseWrapper.i"
namespace std {
%template(int_vector) vector<int>;
%template(float_vector) vector<float>;
%template(double_vector) vector<double>;
%template(string_vector) vector<std::string>;
%template(material_vector) vector<IfcGeom::Material>;
};