这一层使用python来调用数据什么的,先看看一些科普知识:
boost::python库是pyhon和c++相互交互的框架,可以再python中调用c++的类和方法,也可以让c++调用python的类和方法python自身提供了一个Python/C API用来实现python和c++的交互,boost::python是Python/C API的包装,所以用起来更简单一些。Python对一个动态类型的语言,C++是一个静态类型的语言,对于Python中的变量类型,Boost.Python都有相应的类对应,他们都是boost::python::object的子类。boost::python::object 包装了PyObject *,关于Object的详细成员函数和变量可以看官网:here。
在Python 中,所有的东西都是对象,而所有的对象都拥有一些相同的内容,这些内容在PyObject 中定义,PyObject 是整个Python 对象机制的核心。
[object.h]
typedef struct _object {
PyObject_HEAD
} PyObject;
|
[object.h]
#ifdef Py_TRACE_REFS
/* Define pointers to support a doubly-
linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA \
struct _object *_ob_next; \
struct _object *_ob_prev;
#define _PyObject_EXTRA_INIT 0, 0,
#else
#define _PyObject_HEAD_EXTRA
#define _PyObject_EXTRA_INIT
#endif
/* PyObject_HEAD defines the initial
segment of every PyObject. */
#define PyObject_HEAD \
_PyObject_HEAD_EXTRA \
int ob_refcnt; \
struct _typeobject *ob_type;
|
[object.h]
typedef struct _object {
int ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
|
在PyObject 的定义中,整型变量ob_refcnt 与Python 的内存管理机制有关,它实现了基于引用计数的垃圾收集机制。对于某一个对象A,当有一个新的PyObject *引用该对象时,A 的引用计数应该增加;而当这个PyObject *被删除时,A 的引用计数应该减少。当A 的引用计数减少到0 时,A 就可以从堆上被删除,以释放出内存供别的对象使用。在ob_refcnt 之外,我们注意到ob_type 是一个指向_typeobject 结构体的指针,那么这个结构体是一个什么东西呢?实际上这个结构体对应着Python 内部的一种特殊对象,它是用来指定一个对象类型的类型对象。这个类型对象我们将在后边详细地分析。现在我们看到了,在Python 中,对象机制的核心其实非常简单,一个是引用计数,一个就是类型信息。
在PyObject 中定义了每一个Python 对象都必须有的内容,这些内容将出现在每一个Python 对象所占有的内存的最开始的字节中。这句话的另一个意思是,每一个Python 对象除了必须有这个PyObject 内容外,似乎还应该占有一些额外的内存,放置些其他的东西。没错,倘若所有的Python 对象都只包含PyObject,那Python 中岂不是只有唯一的一种对象了,这可是大大的不妙。在PyObject 中定义的内容仅仅是每一个Python 对象都必须拥有的一部分内容,以我们将在下一章剖析的整数对象为例子,你可以看到对象中除PyObject 之外“其他的东西”究竟是些什么东西。
[intobject.h]
typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;
|
def f(x, y):
if(y =='foo'):
x[3:7]='bar'
else:
x.items += y(3, x)
return x
def getfunc():
return f;
object f(object x, object y){
if(y =="foo")
x.slice(3,7)="bar";
else
x.attr("items")+= y(3, x);
return x;
}
object getfunc(){
return object(f);
}
double d=python::extract<double>(obj)
boost::python::object o(boost::python::handle<>(pyobj));
boost::python::object o(boost::python::handle<>(boost::python::borrowed(pyobj)));
Py_INCREF ,当O对象生命周期结束 ,pyobj不会析析构掉
obj.ptr()
python_layer头文件:
#ifndef CAFFE_PYTHON_LAYER_HPP_ #define CAFFE_PYTHON_LAYER_HPP_ #include <boost/python.hpp> #include <vector> #include "caffe/layer.hpp" namespace bp = boost::python; namespace caffe { template <typename Dtype> class PythonLayer : public Layer<Dtype> { public: //通过PyObject,输入参数的内容 PythonLayer(PyObject* self, const LayerParameter& param) : Layer<Dtype>(param), self_(bp::handle<>(bp::borrowed(self))) { } //输入数据 virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { self_.attr("param_str") = bp::str( this->layer_param_.python_param().param_str()); self_.attr("setup")(bottom, top); } //调整数据的形状 virtual void Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { self_.attr("reshape")(bottom, top); } //采用并行线程 virtual inline bool ShareInParallel() const { return this->layer_param_.python_param().share_in_parallel(); } virtual inline const char* type() const { return "Python"; } protected: //前向传播 virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { self_.attr("forward")(bottom, top); } //后向传播 virtual void Backward_cpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { self_.attr("backward")(top, propagate_down, bottom); } private: //私有变量,不允许更改 bp::object self_; }; } // namespace caffe #endif