FreeCAD中对象属性的Python访问机制

FreeCAD中对象属性的Python访问机制,第1张

概述FreeCAD中对象属性的Python访问机制济南友泉软件有限公司 在Part模块一节中,对Part模块的主要组件以及原理进行了较为详细的介绍。但有一个遗留问题,即Python脚本中是如何实现对Part::Feature及其子类的属性访问的呢?Part::Face继承自Part::Feature,因此,可以通过Part::Face为例 FreeCAD中对象属性的Python访问机制济南友泉软件有限公司

 

在Part模块一节中,对Part模块的主要组件以及原理进行了较为详细的介绍。但有一个遗留问题,即Python脚本中是如何实现对Part::Feature及其子类的属性访问的呢?Part::Face继承自Part::Feature,因此,可以通过Part::Face为例来说明Python中Part::Face相关属性的访问过程。

一、Python C扩展的原理

在剖析Part::Face代码实现实现之前,需要先要了解一下Python C扩展的原理,具体来说是使用cpython API来扩展Python类型。本节以Part::PartFeaturePy为例先说明Python扩展类型的注册方法。

使用cpython扩展Python类型,实质是通过cpython API向cpython注册类型相关的信息,这是PyTypeObject这个结构体来描述的,

/// Type structure of PartFeaturePyPyTypeObject PartFeaturePy::Type = {    PyVarObject_head_INIT(&PyType_Type,0)    "Part.Feature",     /*tp_name*/    sizeof(PartFeaturePy),                       /*tp_basicsize*/    0,                                                /*tp_itemsize*/    /* methods */    PyDestructor,                                     /*tp_dealloc*/    0,                                                /*tp_print*/    0,                                                /*tp_getattr*/    0,                                                /*tp_setattr*/    0,                                                /*tp_compare*/    __repr,                                           /*tp_repr*/    0,                                                /*tp_as_number*/    0,                                                /*tp_as_sequence*/    0,                                                /*tp_as_mapPing*/    0,                                                /*tp_hash*/    0,                                                /*tp_call */    0,                                                /*tp_str  */    __getattro,                                       /*tp_getattro*/    __setattro,                                       /*tp_setattro*/    /* --- Functions to access object as input/output buffer ---------*/    0,                                                /* tp_as_buffer */    /* --- Flags to define presence of optional/expanded features */#if PY_MAJOR_VERSION >= 3    Py_TPFLAGS_BASETYPE|Py_TPFLAGS_DEFAulT,        /*tp_flags */#else    Py_TPFLAGS_DEFAulT,        /*tp_flags */#endif    "This is the father of all shape object classes",           /*tp_doc */    0,                                                /*tp_traverse */    0,                                                /*tp_clear */    0,                                                /*tp_richcompare */    0,                                                /*tp_weaklistoffset */    0,                                                /*tp_iter */    0,                                                /*tp_iternext */    Part::PartFeaturePy::Methods,                     /*tp_methods */    0,                                                /*tp_members */    Part::PartFeaturePy::GetterSetter,                     /*tp_getset */    &App::GeoFeaturePy::Type,                        /*tp_base */    0,                                                /*tp_dict */    0,                                                /*tp_descr_get */    0,                                                /*tp_descr_set */    0,                                                /*tp_dictoffset */    __PyInit,                                         /*tp_init */    0,                                                /*tp_alloc */    Part::PartFeaturePy::PyMake,/*tp_new */    0,                                                /*tp_free   Low-level free-memory routine */    0,                                                /*tp_is_gc  For PyObject_IS_GC */    0,                                                /*tp_bases */    0,                                                /*tp_mro    method resolution order */    0,                                                /*tp_cache */    0,                                                /*tp_subclasses */    0,                                                /*tp_weakList */    0,                                                /*tp_del */    0                                                 /*tp_version_tag */#if PY_MAJOR_VERSION >= 3    ,0                                                /*tp_finalize */#endif};

 从上面的代码可以看出,PartFeaturePy注册了Base::PyObjectBase::__getattro()与Base::PyObjectBase::__setattro()来获取与设置属性。实际上,当在Python脚本中通过”.”运算符访问Python扩展类型时,调用的就是注册的这两个函数。

 

二、Part::Face    2.1 获取PartFeaturePy

当在Python脚本中创建Part::Feature对象时,

face1 = App.Activedocument.addobject('Part::Face', 'Face1')

由于App.Activedocument.addobject()实际关联到documentPy::addobject(),而documentPy::addobject()则是通过调用getPyObject()返回关联的Python扩展类型。

在FreeCAD中,虽然没有提供与Part::Face直接对应的Python扩展类型,但是通过继承自Part::Feature,Part::Face关联到了Part::PartFeaturePy这个Python扩展类型。

namespace App {/// @cond DOXERRPROPERTY_SOURCE_TEMPLATE(Part::FeaturePython, Part::Feature)template<> const char* Part::FeaturePython::getVIEwProvIDername(voID) const {    return "PartGui::VIEwProvIDerPython";}template<> PyObject* Part::FeaturePython::getPyObject(voID) {    if (PythonObject.is(Py::_None())) {        // ref counter is set to 1        PythonObject = Py::Object(new FeaturePythonPyT<Part::PartFeaturePy>(this),true);    }    return Py::new_reference_to(PythonObject);}/// @endcond// explicit template instantiationtemplate class PartExport FeaturePythonT<Part::Feature>;}
    2.2 访问属性

从前面的分析可知,如果访问Part::Feature的Sources属性,则会出发调用Base::PyObjectBase::__getattro()函数,最终会调用PropertyContainerPy::getCustomAttributes()这一非虚函数,

PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const{    // search in PropertyList    if(FC_LOG_INSTANCE.level()>FC_LOGLEVEL_TRACE) {        FC_TRACE("Get property " << attr);    }    Property *prop = getPropertyContainerPtr()->getPropertyByname(attr);    if (prop) {        PyObject* pyobj = prop->getPyObject();        if (!pyobj && PyErr_Occurred()) {            // the Python exception is already set            throw Py::Exception();        }        return pyobj;    }    else if (Base::streq(attr, "__dict__")) {        // get the propertIEs to the C++ PropertyContainer class        std::map<std::string,App::Property*> Map;        getPropertyContainerPtr()->getPropertyMap(Map);        PyObject *dict = PyDict_New();        if (dict) {            for ( std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it )#if PY_MAJOR_VERSION >= 3                PyDict_SetItem(dict, PyUnicode_FromString(it->first.c_str()), PyUnicode_FromString(""));#else                PyDict_SetItem(dict, PyString_FromString(it->first.c_str()), PyString_FromString(""));#endif            if (PyErr_Occurred()) {                Py_DECREF(dict);                dict = NulL;            }        }        return dict;    } else if(Base::streq(attr,"Shape")            && getPropertyContainerPtr()->isDerivedFrom(App::documentObject::getClasstypeID()))     {        // Special treatment of Shape property        static PyObject *_getShape = 0;        if(!_getShape) {            _getShape = Py_None;            PyObject *mod = Pyimport_importModule("Part");            if(!mod) {                PyErr_Clear();            } else {                Py::Object pyMod = Py::asObject(mod);                if(pyMod.hasAttr("getShape"))                    _getShape = Py::new_reference_to(pyMod.getAttr("getShape"));            }        }        if(_getShape != Py_None) {            Py::Tuple args(1);            args.setItem(0,Py::Object(const_cast<PropertyContainerPy*>(this)));            auto res = PyObject_CallObject(_getShape, args.ptr());            if(!res)                 PyErr_Clear();            else {                Py::Object pyres(res,true);                if(pyres.hasAttr("isNull")) {                    Py::Callable func(pyres.getAttr("isNull"));                    if(!func.apply().isTrue())                        return Py::new_reference_to(res);                }            }        }    }    return 0;}

从上面的代码可以看出,正是在这个函数完成根据属性名映射到了属性扩展类型。

 

参考资料PyCXXPyCXX Python3FreeCADWeb 总结

以上是内存溢出为你收集整理的FreeCAD中对象属性的Python访问机制全部内容,希望文章能够帮你解决FreeCAD中对象属性的Python访问机制所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/1186058.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存