}
else if (PyFloat_Check(o))
{
- dv = dnn::DictValue(PyFloat_AS_DOUBLE(o));
+ dv = dnn::DictValue(PyFloat_AsDouble(o));
return true;
}
- else if (PyString_Check(o))
+ else
{
- dv = dnn::DictValue(String(PyString_AsString(o)));
- return true;
+ std::string str;
+ if (getUnicodeString(o, str))
+ {
+ dv = dnn::DictValue(str);
+ return true;
+ }
}
- else
- return false;
+ return false;
}
template<>
PyObject* args = PyList_New(inputs.size());
for(size_t i = 0; i < inputs.size(); ++i)
- PyList_SET_ITEM(args, i, pyopencv_from_generic_vec(inputs[i]));
+ PyList_SetItem(args, i, pyopencv_from_generic_vec(inputs[i]));
PyObject* res = PyObject_CallMethodObjArgs(o, PyString_FromString("getMemoryShapes"), args, NULL);
Py_DECREF(args);
return true;
if(PyDict_Check(o)) {
- while(PyDict_Next(o, &pos, &key, &item)) {
- if( !PyString_Check(key) ) {
+ while(PyDict_Next(o, &pos, &key, &item))
+ {
+ // get key
+ std::string k;
+ if (!getUnicodeString(key, k))
+ {
ok = false;
break;
}
-
- String k = PyString_AsString(key);
- if( PyString_Check(item) )
+ // get value
+ if( !!PyBool_Check(item) )
{
- const char* value = PyString_AsString(item);
- p.setString(k, value);
- }
- else if( !!PyBool_Check(item) )
p.setBool(k, item == Py_True);
+ }
else if( PyInt_Check(item) )
{
int value = (int)PyInt_AsLong(item);
}
else
{
- ok = false;
- break;
+ std::string val_str;
+ if (!getUnicodeString(item, val_str))
+ {
+ ok = false;
+ break;
+ }
+ p.setString(k, val_str);
}
}
}
dist = (cvflann::flann_distance_t)d;
return ok;
}
-#endif
\ No newline at end of file
+#endif
endif()
set(cv2_generated_files
- "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h"
+ "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_enums.h"
"${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_funcs.h"
+ "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h"
+ "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_modules.h"
+ "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_modules_content.h"
"${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_types.h"
- "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_type_reg.h"
- "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_ns_reg.h"
+ "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_types_content.h"
"${OPENCV_PYTHON_SIGNATURES_FILE}"
)
add_dependencies(${the_module} gen_opencv_python_source)
endif()
+ocv_assert(${PYTHON}_VERSION_MAJOR)
+ocv_assert(${PYTHON}_VERSION_MINOR)
+
+if(${PYTHON}_LIMITED_API)
+ # support only python3.3+
+ ocv_assert(${PYTHON}_VERSION_MAJOR EQUAL 3 AND ${PYTHON}_VERSION_MINOR GREATER 2)
+ target_compile_definitions(${the_module} PRIVATE CVPY_DYNAMIC_INIT)
+ if(WIN32)
+ string(REPLACE
+ "python${${PYTHON}_VERSION_MAJOR}${${PYTHON}_VERSION_MINOR}.lib"
+ "python${${PYTHON}_VERSION_MAJOR}.lib"
+ ${PYTHON}_LIBRARIES
+ "${${PYTHON}_LIBRARIES}")
+ endif()
+endif()
+
if(APPLE)
set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
elseif(WIN32 OR OPENCV_FORCE_PYTHON_LIBS)
if(NOT PYTHON_CVPY_PROCESS EQUAL 0)
set(CVPY_SUFFIX ".so")
endif()
+ if(${PYTHON}_LIMITED_API)
+ if(WIN32)
+ string(REGEX REPLACE "\\.[^\\.]*\\." "." CVPY_SUFFIX "${CVPY_SUFFIX}")
+ else()
+ string(REGEX REPLACE "\\.[^\\.]*\\." ".abi${${PYTHON}_VERSION_MAJOR}." CVPY_SUFFIX "${CVPY_SUFFIX}")
+ endif()
+ endif()
endif()
ocv_update(OPENCV_PYTHON_EXTENSION_BUILD_PATH "${LIBRARY_OUTPUT_PATH}/${MODULE_INSTALL_SUBDIR}")
set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${${PYTHON}_PACKAGES_PATH} COMPONENT python)
endif()
-ocv_assert(${PYTHON}_VERSION_MAJOR)
-ocv_assert(${PYTHON}_VERSION_MINOR)
-
set(__python_loader_subdir "")
if(NOT OPENCV_SKIP_PYTHON_LOADER)
set(__python_loader_subdir "cv2/")
ocv_module_disable(python3)
endif()
+# Problem in numpy >=1.15 <1.17
+if(PYTHON3_LIMITED_API
+ AND NOT PYTHON3_NUMPY_VERSION VERSION_LESS "1.15"
+ AND PYTHON3_NUMPY_VERSION VERSION_LESS "1.17"
+ )
+ set(PYTHON3_LIMITED_API OFF)
+endif()
+
set(the_description "The python3 bindings")
set(MODULE_NAME python3)
set(MODULE_INSTALL_SUBDIR python3)
#pragma warning(push)
#pragma warning(disable:5033) // 'register' is no longer a supported storage class
#endif
+
+// #define CVPY_DYNAMIC_INIT
+// #define Py_DEBUG
+
+#if defined(CVPY_DYNAMIC_INIT) && !defined(Py_DEBUG)
+# define Py_LIMITED_API 0x03030000
+#endif
+
#include <math.h>
#include <Python.h>
+
+#if PY_MAJOR_VERSION < 3
+#undef CVPY_DYNAMIC_INIT
+#endif
+
#if defined(_MSC_VER) && (_MSC_VER > 1800)
#pragma warning(pop)
#endif
+#define MODULESTR "cv2"
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#include <numpy/ndarrayobject.h>
+
+#include "pyopencv_generated_include.h"
+#include "opencv2/core/types_c.h"
+#include "opencv2/opencv_modules.hpp"
+#include "pycompat.hpp"
+#include <map>
+
template<typename T, class TEnable = void> // TEnable is used for SFINAE checks
struct PyOpenCV_Converter
{
template<typename T> static
PyObject* pyopencv_from(const T& src) { return PyOpenCV_Converter<T>::from(src); }
-
-#define CV_PY_FN_WITH_KW_(fn, flags) (PyCFunction)(void*)(PyCFunctionWithKeywords)(fn), (flags) | METH_VARARGS | METH_KEYWORDS
-#define CV_PY_FN_NOARGS_(fn, flags) (PyCFunction)(fn), (flags) | METH_NOARGS
-
-#define CV_PY_FN_WITH_KW(fn) CV_PY_FN_WITH_KW_(fn, 0)
-#define CV_PY_FN_NOARGS(fn) CV_PY_FN_NOARGS_(fn, 0)
-
-
-#define MODULESTR "cv2"
-#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
-#include <numpy/ndarrayobject.h>
-
-#if PY_MAJOR_VERSION >= 3
-# define CV_PYTHON_TYPE_HEAD_INIT() PyVarObject_HEAD_INIT(&PyType_Type, 0)
-#else
-# define CV_PYTHON_TYPE_HEAD_INIT() PyObject_HEAD_INIT(&PyType_Type) 0,
-#endif
-
-#define CV_PY_TO_CLASS(TYPE) \
-template<> \
-bool pyopencv_to(PyObject* dst, TYPE& src, const char* name) \
-{ \
- if (!dst || dst == Py_None) \
- return true; \
- Ptr<TYPE> ptr; \
- \
- if (!pyopencv_to(dst, ptr, name)) return false; \
- src = *ptr; \
- return true; \
-}
-
-#define CV_PY_FROM_CLASS(TYPE) \
-template<> \
-PyObject* pyopencv_from(const TYPE& src) \
-{ \
- Ptr<TYPE> ptr(new TYPE()); \
- \
- *ptr = src; \
- return pyopencv_from(ptr); \
-}
-
-#define CV_PY_TO_CLASS_PTR(TYPE) \
-template<> \
-bool pyopencv_to(PyObject* dst, TYPE*& src, const char* name) \
-{ \
- if (!dst || dst == Py_None) \
- return true; \
- Ptr<TYPE> ptr; \
- \
- if (!pyopencv_to(dst, ptr, name)) return false; \
- src = ptr; \
- return true; \
-}
-
-#define CV_PY_FROM_CLASS_PTR(TYPE) \
-static PyObject* pyopencv_from(TYPE*& src) \
-{ \
- return pyopencv_from(Ptr<TYPE>(src)); \
-}
-
-#define CV_PY_TO_ENUM(TYPE) \
-template<> \
-bool pyopencv_to(PyObject* dst, TYPE& src, const char* name) \
-{ \
- if (!dst || dst == Py_None) \
- return true; \
- int underlying = 0; \
- \
- if (!pyopencv_to(dst, underlying, name)) return false; \
- src = static_cast<TYPE>(underlying); \
- return true; \
-}
-
-#define CV_PY_FROM_ENUM(TYPE) \
-template<> \
-PyObject* pyopencv_from(const TYPE& src) \
-{ \
- return pyopencv_from(static_cast<int>(src)); \
-}
-
-#include "pyopencv_generated_include.h"
-#include "opencv2/core/types_c.h"
-
-#include "opencv2/opencv_modules.hpp"
-
-#include "pycompat.hpp"
-
-#include <map>
-
static PyObject* opencv_error = NULL;
static int failmsg(const char *fmt, ...)
m = Mat(sz, 1, CV_64F);
for( i = 0; i < sz; i++ )
{
- PyObject* oi = PyTuple_GET_ITEM(o, i);
+ PyObject* oi = PyTuple_GetItem(o, i);
if( PyInt_Check(oi) )
m.at<double>(i) = (double)PyInt_AsLong(oi);
else if( PyFloat_Check(oi) )
return PyLong_FromVoidPtr(ptr);
}
+struct SafeSeqItem
+{
+ PyObject * item;
+ SafeSeqItem(PyObject *obj, size_t idx) { item = PySequence_GetItem(obj, idx); }
+ ~SafeSeqItem() { Py_XDECREF(item); }
+};
+
static bool pyopencv_to(PyObject *o, Scalar& s, const ArgInfo info)
{
if(!o || o == Py_None)
return true;
if (PySequence_Check(o)) {
- PyObject *fi = PySequence_Fast(o, info.name);
- if (fi == NULL)
- return false;
- if (4 < PySequence_Fast_GET_SIZE(fi))
+ if (4 < PySequence_Size(o))
{
failmsg("Scalar value for argument '%s' is longer than 4", info.name);
return false;
}
- for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(fi); i++) {
- PyObject *item = PySequence_Fast_GET_ITEM(fi, i);
+ for (Py_ssize_t i = 0; i < PySequence_Size(o); i++) {
+ SafeSeqItem item_wrap(o, i);
+ PyObject *item = item_wrap.item;
if (PyFloat_Check(item) || PyInt_Check(item)) {
s[(int)i] = PyFloat_AsDouble(item);
} else {
return false;
}
}
- Py_DECREF(fi);
} else {
if (PyFloat_Check(o) || PyInt_Check(o)) {
s[0] = PyFloat_AsDouble(o);
}
template<>
-bool pyopencv_to(PyObject* obj, String& value, const char* name)
+bool pyopencv_to(PyObject* obj, String &value, const char* name)
{
CV_UNUSED(name);
if(!obj || obj == Py_None)
return true;
- const char* str = PyString_AsString(obj);
- if(!str)
- return false;
- value = String(str);
- return true;
+ std::string str;
+ if (getUnicodeString(obj, str))
+ {
+ value = str;
+ return true;
+ }
+ return false;
}
template<>
return true;
while (PySequence_Check(obj))
{
- PyObject *fi = PySequence_Fast(obj, name);
- if (fi == NULL)
- break;
- if (2 != PySequence_Fast_GET_SIZE(fi))
+ if (2 != PySequence_Size(obj))
{
failmsg("Range value for argument '%s' is longer than 2", name);
- Py_DECREF(fi);
return false;
}
{
- PyObject *item = PySequence_Fast_GET_ITEM(fi, 0);
+ SafeSeqItem item_wrap(obj, 0);
+ PyObject *item = item_wrap.item;
if (PyInt_Check(item)) {
r.start = (int)PyInt_AsLong(item);
} else {
failmsg("Range.start value for argument '%s' is not integer", name);
- Py_DECREF(fi);
break;
}
}
{
- PyObject *item = PySequence_Fast_GET_ITEM(fi, 1);
+ SafeSeqItem item_wrap(obj, 1);
+ PyObject *item = item_wrap.item;
if (PyInt_Check(item)) {
r.end = (int)PyInt_AsLong(item);
} else {
failmsg("Range.end value for argument '%s' is not integer", name);
- Py_DECREF(fi);
break;
}
}
- Py_DECREF(fi);
return true;
}
if(PyObject_Size(obj) == 0)
CV_UNUSED(name);
if(!obj || obj == Py_None)
return true;
- if(!!PyComplex_CheckExact(obj))
+ if(PyComplex_Check(obj))
{
- Py_complex c = PyComplex_AsCComplex(obj);
- p.x = saturate_cast<int>(c.real);
- p.y = saturate_cast<int>(c.imag);
+ p.x = saturate_cast<int>(PyComplex_RealAsDouble(obj));
+ p.y = saturate_cast<int>(PyComplex_ImagAsDouble(obj));
return true;
}
return PyArg_ParseTuple(obj, "ii", &p.x, &p.y) > 0;
CV_UNUSED(name);
if(!obj || obj == Py_None)
return true;
- if(!!PyComplex_CheckExact(obj))
+ if (PyComplex_Check(obj))
{
- Py_complex c = PyComplex_AsCComplex(obj);
- p.x = saturate_cast<float>(c.real);
- p.y = saturate_cast<float>(c.imag);
+ p.x = saturate_cast<float>(PyComplex_RealAsDouble(obj));
+ p.y = saturate_cast<float>(PyComplex_ImagAsDouble(obj));
return true;
}
return PyArg_ParseTuple(obj, "ff", &p.x, &p.y) > 0;
CV_UNUSED(name);
if(!obj || obj == Py_None)
return true;
- if(!!PyComplex_CheckExact(obj))
+ if(PyComplex_Check(obj))
{
- Py_complex c = PyComplex_AsCComplex(obj);
- p.x = saturate_cast<double>(c.real);
- p.y = saturate_cast<double>(c.imag);
+ p.x = PyComplex_RealAsDouble(obj);
+ p.y = PyComplex_ImagAsDouble(obj);
return true;
}
return PyArg_ParseTuple(obj, "dd", &p.x, &p.y) > 0;
template<typename _Tp> struct pyopencvVecConverter
{
+ typedef typename DataType<_Tp>::channel_type _Cp;
+ static inline bool copyOneItem(PyObject *obj, size_t start, int channels, _Cp * data)
+ {
+ for(size_t j = 0; (int)j < channels; j++ )
+ {
+ SafeSeqItem sub_item_wrap(obj, start + j);
+ PyObject* item_ij = sub_item_wrap.item;
+ if( PyInt_Check(item_ij))
+ {
+ int v = (int)PyInt_AsLong(item_ij);
+ if( v == -1 && PyErr_Occurred() )
+ return false;
+ data[j] = saturate_cast<_Cp>(v);
+ }
+ else if( PyLong_Check(item_ij))
+ {
+ int v = (int)PyLong_AsLong(item_ij);
+ if( v == -1 && PyErr_Occurred() )
+ return false;
+ data[j] = saturate_cast<_Cp>(v);
+ }
+ else if( PyFloat_Check(item_ij))
+ {
+ double v = PyFloat_AsDouble(item_ij);
+ if( PyErr_Occurred() )
+ return false;
+ data[j] = saturate_cast<_Cp>(v);
+ }
+ else
+ return false;
+ }
+ return true;
+ }
static bool to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info)
{
- typedef typename DataType<_Tp>::channel_type _Cp;
if(!obj || obj == Py_None)
return true;
if (PyArray_Check(obj))
Mat m;
pyopencv_to(obj, m, info);
m.copyTo(value);
+ return true;
}
- if (!PySequence_Check(obj))
- return false;
- PyObject *seq = PySequence_Fast(obj, info.name);
- if (seq == NULL)
- return false;
- int i, j, n = (int)PySequence_Fast_GET_SIZE(seq);
- value.resize(n);
-
- int type = traits::Type<_Tp>::value;
- int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
- PyObject** items = PySequence_Fast_ITEMS(seq);
-
- for( i = 0; i < n; i++ )
+ else if (PySequence_Check(obj))
{
- PyObject* item = items[i];
- PyObject* seq_i = 0;
- PyObject** items_i = &item;
- _Cp* data = (_Cp*)&value[i];
-
- if( channels == 2 && PyComplex_CheckExact(item) )
+ const int type = traits::Type<_Tp>::value;
+ const int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
+ size_t i, n = PySequence_Size(obj);
+ value.resize(n);
+ for (i = 0; i < n; i++ )
{
- Py_complex c = PyComplex_AsCComplex(obj);
- data[0] = saturate_cast<_Cp>(c.real);
- data[1] = saturate_cast<_Cp>(c.imag);
- continue;
- }
- if( channels > 1 )
- {
- if( PyArray_Check(item))
- {
- Mat src;
- pyopencv_to(item, src, info);
- if( src.dims != 2 || src.channels() != 1 ||
- ((src.cols != 1 || src.rows != channels) &&
- (src.cols != channels || src.rows != 1)))
- break;
- Mat dst(src.rows, src.cols, depth, data);
- src.convertTo(dst, type);
- if( dst.data != (uchar*)data )
- break;
- continue;
- }
-
- seq_i = PySequence_Fast(item, info.name);
- if( !seq_i || (int)PySequence_Fast_GET_SIZE(seq_i) != channels )
- {
- Py_XDECREF(seq_i);
- break;
- }
- items_i = PySequence_Fast_ITEMS(seq_i);
- }
+ SafeSeqItem item_wrap(obj, i);
+ PyObject* item = item_wrap.item;
+ _Cp* data = (_Cp*)&value[i];
- for( j = 0; j < channels; j++ )
- {
- PyObject* item_ij = items_i[j];
- if( PyInt_Check(item_ij))
+ if( channels == 2 && PyComplex_Check(item) )
{
- int v = (int)PyInt_AsLong(item_ij);
- if( v == -1 && PyErr_Occurred() )
- break;
- data[j] = saturate_cast<_Cp>(v);
+ data[0] = saturate_cast<_Cp>(PyComplex_RealAsDouble(item));
+ data[1] = saturate_cast<_Cp>(PyComplex_ImagAsDouble(item));
}
- else if( PyLong_Check(item_ij))
+ else if( channels > 1 )
{
- int v = (int)PyLong_AsLong(item_ij);
- if( v == -1 && PyErr_Occurred() )
+ if( PyArray_Check(item))
+ {
+ Mat src;
+ pyopencv_to(item, src, info);
+ if( src.dims != 2 || src.channels() != 1 ||
+ ((src.cols != 1 || src.rows != channels) &&
+ (src.cols != channels || src.rows != 1)))
+ break;
+ Mat dst(src.rows, src.cols, depth, data);
+ src.convertTo(dst, type);
+ if( dst.data != (uchar*)data )
+ break;
+ }
+ else if (PySequence_Check(item))
+ {
+ if (!copyOneItem(item, 0, channels, data))
+ break;
+ }
+ else
+ {
break;
- data[j] = saturate_cast<_Cp>(v);
+ }
}
- else if( PyFloat_Check(item_ij))
+ else if (channels == 1)
{
- double v = PyFloat_AsDouble(item_ij);
- if( PyErr_Occurred() )
+ if (!copyOneItem(obj, i, channels, data))
break;
- data[j] = saturate_cast<_Cp>(v);
}
else
+ {
break;
+ }
}
- Py_XDECREF(seq_i);
- if( j < channels )
- break;
+ return i == n;
}
- Py_DECREF(seq);
- return i == n;
+ return false;
}
static PyObject* from(const std::vector<_Tp>& value)
return true;
if (!PySequence_Check(obj))
return false;
- PyObject *seq = PySequence_Fast(obj, info.name);
- if (seq == NULL)
- return false;
- int i, n = (int)PySequence_Fast_GET_SIZE(seq);
+ size_t n = PySequence_Size(obj);
value.resize(n);
-
- PyObject** items = PySequence_Fast_ITEMS(seq);
-
- for( i = 0; i < n; i++ )
+ for(size_t i = 0; i < n; i++ )
{
- PyObject* item = items[i];
- if(!pyopencv_to(item, value[i], info))
- break;
+ SafeSeqItem item_wrap(obj, i);
+ if(!pyopencv_to(item_wrap.item, value[i], info))
+ return false;
}
- Py_DECREF(seq);
- return i == n;
+ return true;
}
template<typename _Tp> static inline PyObject* pyopencv_from_generic_vec(const std::vector<_Tp>& value)
PyObject* item = pyopencv_from(value[i]);
if(!item)
break;
- PyList_SET_ITEM(seq, i, item);
+ PyList_SetItem(seq, i, item);
}
if( i < n )
{
static int convert_to_char(PyObject *o, char *dst, const char *name = "no_name")
{
- if (PyString_Check(o) && PyString_Size(o) == 1) {
- *dst = PyString_AsString(o)[0];
- return 1;
- } else {
+ std::string str;
+ if (getUnicodeString(o, str))
+ {
+ *dst = str[0];
+ return 1;
+ }
(*dst) = 0;
return failmsg("Expected single character string for argument '%s'", name);
- }
}
-#if PY_MAJOR_VERSION >= 3
-#define MKTYPE2(NAME) pyopencv_##NAME##_specials(); if (!to_ok(&pyopencv_##NAME##_Type)) return NULL;
-#else
-#define MKTYPE2(NAME) pyopencv_##NAME##_specials(); if (!to_ok(&pyopencv_##NAME##_Type)) return
-#endif
-
#ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
+
#include "pyopencv_generated_enums.h"
#include "pyopencv_custom_headers.h"
+
+#ifdef CVPY_DYNAMIC_INIT
+#define CVPY_TYPE(NAME, STORAGE, SNAME, _1, _2) CVPY_TYPE_DECLARE_DYNAMIC(NAME, STORAGE, SNAME)
+#else
+#define CVPY_TYPE(NAME, STORAGE, SNAME, _1, _2) CVPY_TYPE_DECLARE(NAME, STORAGE, SNAME)
+#endif
#include "pyopencv_generated_types.h"
+#undef CVPY_TYPE
+
+#include "pyopencv_generated_types_content.h"
#include "pyopencv_generated_funcs.h"
+
static PyMethodDef special_methods[] = {
{"redirectError", CV_PY_FN_WITH_KW(pycvRedirectError), "redirectError(onError) -> None"},
#ifdef HAVE_OPENCV_HIGHGUI
}
-#include "pyopencv_generated_ns_reg.h"
+#include "pyopencv_generated_modules_content.h"
-static int to_ok(PyTypeObject *to)
+static bool init_body(PyObject * m)
{
- to->tp_alloc = PyType_GenericAlloc;
- to->tp_new = PyType_GenericNew;
- to->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
- return (PyType_Ready(to) == 0);
-}
+#define CVPY_MODULE(NAMESTR, NAME) \
+ init_submodule(m, MODULESTR NAMESTR, methods_##NAME, consts_##NAME)
+ #include "pyopencv_generated_modules.h"
+#undef CVPY_MODULE
+
+#ifdef CVPY_DYNAMIC_INIT
+#define CVPY_TYPE(NAME, _1, _2, BASE, CONSTRUCTOR) CVPY_TYPE_INIT_DYNAMIC(NAME, return false, BASE, CONSTRUCTOR)
+ PyObject * pyopencv_NoBase_TypePtr = NULL;
+#else
+#define CVPY_TYPE(NAME, _1, _2, BASE, CONSTRUCTOR) CVPY_TYPE_INIT_STATIC(NAME, return false, BASE, CONSTRUCTOR)
+ PyTypeObject * pyopencv_NoBase_TypePtr = NULL;
+#endif
+ #include "pyopencv_generated_types.h"
+#undef CVPY_TYPE
+
+ PyObject* d = PyModule_GetDict(m);
+ PyDict_SetItemString(d, "__version__", PyString_FromString(CV_VERSION));
+
+ PyObject *opencv_error_dict = PyDict_New();
+ PyDict_SetItemString(opencv_error_dict, "file", Py_None);
+ PyDict_SetItemString(opencv_error_dict, "func", Py_None);
+ PyDict_SetItemString(opencv_error_dict, "line", Py_None);
+ PyDict_SetItemString(opencv_error_dict, "code", Py_None);
+ PyDict_SetItemString(opencv_error_dict, "msg", Py_None);
+ PyDict_SetItemString(opencv_error_dict, "err", Py_None);
+ opencv_error = PyErr_NewException((char*)MODULESTR".error", NULL, opencv_error_dict);
+ Py_DECREF(opencv_error_dict);
+ PyDict_SetItemString(d, "error", opencv_error);
+
+
+#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I))
+ PUBLISH(CV_8U);
+ PUBLISH(CV_8UC1);
+ PUBLISH(CV_8UC2);
+ PUBLISH(CV_8UC3);
+ PUBLISH(CV_8UC4);
+ PUBLISH(CV_8S);
+ PUBLISH(CV_8SC1);
+ PUBLISH(CV_8SC2);
+ PUBLISH(CV_8SC3);
+ PUBLISH(CV_8SC4);
+ PUBLISH(CV_16U);
+ PUBLISH(CV_16UC1);
+ PUBLISH(CV_16UC2);
+ PUBLISH(CV_16UC3);
+ PUBLISH(CV_16UC4);
+ PUBLISH(CV_16S);
+ PUBLISH(CV_16SC1);
+ PUBLISH(CV_16SC2);
+ PUBLISH(CV_16SC3);
+ PUBLISH(CV_16SC4);
+ PUBLISH(CV_32S);
+ PUBLISH(CV_32SC1);
+ PUBLISH(CV_32SC2);
+ PUBLISH(CV_32SC3);
+ PUBLISH(CV_32SC4);
+ PUBLISH(CV_32F);
+ PUBLISH(CV_32FC1);
+ PUBLISH(CV_32FC2);
+ PUBLISH(CV_32FC3);
+ PUBLISH(CV_32FC4);
+ PUBLISH(CV_64F);
+ PUBLISH(CV_64FC1);
+ PUBLISH(CV_64FC2);
+ PUBLISH(CV_64FC3);
+ PUBLISH(CV_64FC4);
+#undef PUBLISH
+
+ return true;
+}
+
#if defined(__GNUC__)
#pragma GCC visibility push(default)
#endif
#if PY_MAJOR_VERSION >= 3
-PyMODINIT_FUNC PyInit_cv2();
+// === Python 3
+
static struct PyModuleDef cv2_moduledef =
{
PyModuleDef_HEAD_INIT,
special_methods
};
+PyMODINIT_FUNC PyInit_cv2();
PyObject* PyInit_cv2()
+{
+ import_array(); // from numpy
+ PyObject* m = PyModule_Create(&cv2_moduledef);
+ if (!init_body(m))
+ return NULL;
+ return m;
+}
+
#else
+// === Python 2
PyMODINIT_FUNC initcv2();
-
void initcv2()
-#endif
{
- import_array();
-
-#include "pyopencv_generated_type_reg.h"
-
-#if PY_MAJOR_VERSION >= 3
- PyObject* m = PyModule_Create(&cv2_moduledef);
-#else
- PyObject* m = Py_InitModule(MODULESTR, special_methods);
-#endif
- init_submodules(m); // from "pyopencv_generated_ns_reg.h"
-
- PyObject* d = PyModule_GetDict(m);
-
- PyDict_SetItemString(d, "__version__", PyString_FromString(CV_VERSION));
-
- PyObject *opencv_error_dict = PyDict_New();
- PyDict_SetItemString(opencv_error_dict, "file", Py_None);
- PyDict_SetItemString(opencv_error_dict, "func", Py_None);
- PyDict_SetItemString(opencv_error_dict, "line", Py_None);
- PyDict_SetItemString(opencv_error_dict, "code", Py_None);
- PyDict_SetItemString(opencv_error_dict, "msg", Py_None);
- PyDict_SetItemString(opencv_error_dict, "err", Py_None);
- opencv_error = PyErr_NewException((char*)MODULESTR".error", NULL, opencv_error_dict);
- Py_DECREF(opencv_error_dict);
- PyDict_SetItemString(d, "error", opencv_error);
-
-#if PY_MAJOR_VERSION >= 3
-#define PUBLISH_OBJECT(name, type) Py_INCREF(&type);\
- PyModule_AddObject(m, name, (PyObject *)&type);
-#else
-// Unrolled Py_INCREF(&type) without (PyObject*) cast
-// due to "warning: dereferencing type-punned pointer will break strict-aliasing rules"
-#define PUBLISH_OBJECT(name, type) _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA (&type)->ob_refcnt++;\
- PyModule_AddObject(m, name, (PyObject *)&type);
-#endif
-
-#include "pyopencv_generated_type_publish.h"
-
-#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I))
-//#define PUBLISHU(I) PyDict_SetItemString(d, #I, PyLong_FromUnsignedLong(I))
-#define PUBLISH2(I, value) PyDict_SetItemString(d, #I, PyLong_FromLong(value))
-
- PUBLISH(CV_8U);
- PUBLISH(CV_8UC1);
- PUBLISH(CV_8UC2);
- PUBLISH(CV_8UC3);
- PUBLISH(CV_8UC4);
- PUBLISH(CV_8S);
- PUBLISH(CV_8SC1);
- PUBLISH(CV_8SC2);
- PUBLISH(CV_8SC3);
- PUBLISH(CV_8SC4);
- PUBLISH(CV_16U);
- PUBLISH(CV_16UC1);
- PUBLISH(CV_16UC2);
- PUBLISH(CV_16UC3);
- PUBLISH(CV_16UC4);
- PUBLISH(CV_16S);
- PUBLISH(CV_16SC1);
- PUBLISH(CV_16SC2);
- PUBLISH(CV_16SC3);
- PUBLISH(CV_16SC4);
- PUBLISH(CV_32S);
- PUBLISH(CV_32SC1);
- PUBLISH(CV_32SC2);
- PUBLISH(CV_32SC3);
- PUBLISH(CV_32SC4);
- PUBLISH(CV_32F);
- PUBLISH(CV_32FC1);
- PUBLISH(CV_32FC2);
- PUBLISH(CV_32FC3);
- PUBLISH(CV_32FC4);
- PUBLISH(CV_64F);
- PUBLISH(CV_64FC1);
- PUBLISH(CV_64FC2);
- PUBLISH(CV_64FC3);
- PUBLISH(CV_64FC4);
+ import_array(); // from numpy
+ PyObject* m = Py_InitModule(MODULESTR, special_methods);
+ init_body(m);
+}
-#if PY_MAJOR_VERSION >= 3
- return m;
#endif
-}
pass_by_val_types = ["Point*", "Point2f*", "Rect*", "String*", "double*", "float*", "int*"]
-gen_template_check_self = Template(""" $cname* _self_ = NULL;
- if(PyObject_TypeCheck(self, &pyopencv_${name}_Type))
- _self_ = ${amp}((pyopencv_${name}_t*)self)->v${get};
- if (!_self_)
- return failmsgp("Incorrect type of self (must be '${name}' or its derivative)");
-""")
-
-gen_template_check_self_algo = Template(""" $cname* _self_ = NULL;
- if(PyObject_TypeCheck(self, &pyopencv_${name}_Type))
- _self_ = dynamic_cast<$cname*>(${amp}((pyopencv_${name}_t*)self)->v.get());
- if (!_self_)
+gen_template_check_self = Template("""
+ ${cname} * self1 = 0;
+ if (!pyopencv_${name}_getp(self, self1))
return failmsgp("Incorrect type of self (must be '${name}' or its derivative)");
+ ${pname} _self_ = ${cvt}(self1);
""")
-
gen_template_call_constructor_prelude = Template("""new (&(self->v)) Ptr<$cname>(); // init Ptr with placement new
if(self) """)
}
""")
-head_init_str = "CV_PYTHON_TYPE_HEAD_INIT()"
-
-gen_template_simple_type_decl = Template("""
-struct pyopencv_${name}_t
-{
- PyObject_HEAD
- ${cname} v;
-};
-
-static PyTypeObject pyopencv_${name}_Type =
-{
- %s
- MODULESTR".$wname",
- sizeof(pyopencv_${name}_t),
-};
-
-static void pyopencv_${name}_dealloc(PyObject* self)
-{
- ((pyopencv_${name}_t*)self)->v.${cname}::~${sname}();
- PyObject_Del(self);
-}
-
-template<>
-struct PyOpenCV_Converter< ${cname} >
-{
- static PyObject* from(const ${cname}& r)
- {
- pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
- new (&m->v) ${cname}(r); //Copy constructor
- return (PyObject*)m;
- }
-
- static bool to(PyObject* src, ${cname}& dst, const char* name)
- {
- if(!src || src == Py_None)
- return true;
- if(PyObject_TypeCheck(src, &pyopencv_${name}_Type))
- {
- dst = ((pyopencv_${name}_t*)src)->v;
- return true;
- }
- failmsg("Expected ${cname} for argument '%%s'", name);
- return false;
- }
-};
-""" % head_init_str)
-
gen_template_mappable = Template("""
{
${mappable} _src;
""")
gen_template_type_decl = Template("""
-struct pyopencv_${name}_t
-{
- PyObject_HEAD
- Ptr<${cname1}> v;
-};
-
-static PyTypeObject pyopencv_${name}_Type =
-{
- %s
- MODULESTR".$wname",
- sizeof(pyopencv_${name}_t),
-};
-
-static void pyopencv_${name}_dealloc(PyObject* self)
-{
- ((pyopencv_${name}_t*)self)->v.release();
- PyObject_Del(self);
-}
+// Converter (${name})
template<>
-struct PyOpenCV_Converter< Ptr<${cname}> >
+struct PyOpenCV_Converter< ${cname} >
{
- static PyObject* from(const Ptr<${cname}>& r)
+ static PyObject* from(const ${cname}& r)
{
- pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
- new (&(m->v)) Ptr<$cname1>(); // init Ptr with placement new
- m->v = r;
- return (PyObject*)m;
+ return pyopencv_${name}_Instance(r);
}
-
- static bool to(PyObject* src, Ptr<${cname}>& dst, const char* name)
+ static bool to(PyObject* src, ${cname}& dst, const char* name)
{
if(!src || src == Py_None)
return true;
- if(PyObject_TypeCheck(src, &pyopencv_${name}_Type))
+ ${cname} * dst_;
+ if (pyopencv_${name}_getp(src, dst_))
{
- dst = ((pyopencv_${name}_t*)src)->v.dynamicCast<${cname}>();
+ dst = *dst_;
return true;
}
${mappable_code}
}
};
-""" % head_init_str)
+""")
gen_template_map_type_cvt = Template("""
template<> bool pyopencv_to(PyObject* src, ${cname}& dst, const char* name);
+
""")
gen_template_set_prop_from_map = Template("""
}""")
gen_template_type_impl = Template("""
-static PyObject* pyopencv_${name}_repr(PyObject* self)
-{
- char str[1000];
- sprintf(str, "<$wname %p>", self);
- return PyString_FromString(str);
-}
+// GetSet (${name})
${getset_code}
+// Methods (${name})
+
+${methods_code}
+
+// Tables (${name})
+
static PyGetSetDef pyopencv_${name}_getseters[] =
{${getset_inits}
{NULL} /* Sentinel */
};
-${methods_code}
-
static PyMethodDef pyopencv_${name}_methods[] =
{
${methods_inits}
{NULL, NULL}
};
-
-static void pyopencv_${name}_specials(void)
-{
- pyopencv_${name}_Type.tp_base = ${baseptr};
- pyopencv_${name}_Type.tp_dealloc = pyopencv_${name}_dealloc;
- pyopencv_${name}_Type.tp_repr = pyopencv_${name}_repr;
- pyopencv_${name}_Type.tp_getset = pyopencv_${name}_getseters;
- pyopencv_${name}_Type.tp_init = (initproc)${constructor};
- pyopencv_${name}_Type.tp_methods = pyopencv_${name}_methods;${extra_specials}
-}
""")
methods_code.write(m.gen_code(codegen))
methods_inits.write(m.get_tab_entry())
- baseptr = "NULL"
+ code = gen_template_type_impl.substitute(name=self.name, wname=self.wname, cname=self.cname,
+ getset_code=getset_code.getvalue(), getset_inits=getset_inits.getvalue(),
+ methods_code=methods_code.getvalue(), methods_inits=methods_inits.getvalue())
+
+ return code
+
+ def gen_def(self, codegen):
+ all_classes = codegen.classes
+ baseptr = "NoBase"
if self.base and self.base in all_classes:
- baseptr = "&pyopencv_" + all_classes[self.base].name + "_Type"
+ baseptr = all_classes[self.base].name
constructor_name = "0"
if self.constructor is not None:
constructor_name = self.constructor.get_wrapper_name()
- code = gen_template_type_impl.substitute(name=self.name, wname=self.wname, cname=self.cname,
- getset_code=getset_code.getvalue(), getset_inits=getset_inits.getvalue(),
- methods_code=methods_code.getvalue(), methods_inits=methods_inits.getvalue(),
- baseptr=baseptr, constructor=constructor_name, extra_specials="")
-
- return code
+ return "CVPY_TYPE({}, {}, {}, {}, {});\n".format(
+ self.name,
+ self.cname if self.issimple else "Ptr<{}>".format(self.cname),
+ self.sname if self.issimple else "Ptr",
+ baseptr,
+ constructor_name
+ )
def handle_ptr(tp):
code = "%s\n{\n" % (proto,)
code += " using namespace %s;\n\n" % self.namespace.replace('.', '::')
- selfinfo = ClassInfo("")
+ selfinfo = None
ismethod = self.classname != "" and not self.isconstructor
# full name is needed for error diagnostic in PyArg_ParseTupleAndKeywords
fullname = self.name
if self.classname:
selfinfo = all_classes[self.classname]
if not self.isconstructor:
- amp = "&" if selfinfo.issimple else ""
- if self.is_static:
- pass
- elif selfinfo.isalgorithm:
- code += gen_template_check_self_algo.substitute(name=selfinfo.name, cname=selfinfo.cname, amp=amp)
- else:
- get = "" if selfinfo.issimple else ".get()"
- code += gen_template_check_self.substitute(name=selfinfo.name, cname=selfinfo.cname, amp=amp, get=get)
+ if not self.is_static:
+ code += gen_template_check_self.substitute(
+ name=selfinfo.name,
+ cname=selfinfo.cname if selfinfo.issimple else "Ptr<{}>".format(selfinfo.cname),
+ pname=(selfinfo.cname + '*') if selfinfo.issimple else "Ptr<{}>".format(selfinfo.cname),
+ cvt='' if selfinfo.issimple else '*'
+ )
fullname = selfinfo.wname + "." + fullname
all_code_variants = []
self.code_enums = StringIO()
self.code_types = StringIO()
self.code_funcs = StringIO()
- self.code_type_reg = StringIO()
self.code_ns_reg = StringIO()
+ self.code_ns_init = StringIO()
self.code_type_publish = StringIO()
self.py_signatures = dict()
self.class_idx = 0
self.code_ns_reg.write(' {"%s", static_cast<long>(%s)},\n'%(compat_name, cname))
self.code_ns_reg.write(' {NULL, 0}\n};\n\n')
- def gen_namespaces_reg(self):
- self.code_ns_reg.write('static void init_submodules(PyObject * root) \n{\n')
- for ns_name in sorted(self.namespaces):
- if ns_name.split('.')[0] == 'cv':
- wname = normalize_class_name(ns_name)
- self.code_ns_reg.write(' init_submodule(root, MODULESTR"%s", methods_%s, consts_%s);\n' % (ns_name[2:], wname, wname))
- self.code_ns_reg.write('};\n')
-
def gen_enum_reg(self, enum_name):
name_seg = enum_name.split(".")
is_enum_class = False
classlist = list(self.classes.items())
classlist.sort()
for name, classinfo in classlist:
+ self.code_types.write("//{}\n".format(80*"="))
+ self.code_types.write("// {} ({})\n".format(name, 'Map' if classinfo.ismap else 'Generic'))
+ self.code_types.write("//{}\n".format(80*"="))
+ self.code_types.write(classinfo.gen_code(self))
if classinfo.ismap:
- self.code_types.write(gen_template_map_type_cvt.substitute(name=name, cname=classinfo.cname))
+ self.code_types.write(gen_template_map_type_cvt.substitute(name=classinfo.name, cname=classinfo.cname))
else:
- if classinfo.issimple:
- templ = gen_template_simple_type_decl
- else:
- templ = gen_template_type_decl
mappable_code = "\n".join([
gen_template_mappable.substitute(cname=classinfo.cname, mappable=mappable)
for mappable in classinfo.mappables])
- self.code_types.write(templ.substitute(name=name, wname=classinfo.wname, cname=classinfo.cname, sname=classinfo.sname,
- cname1=("cv::Algorithm" if classinfo.isalgorithm else classinfo.cname), mappable_code=mappable_code))
+ code = gen_template_type_decl.substitute(
+ name=classinfo.name,
+ cname=classinfo.cname if classinfo.issimple else "Ptr<{}>".format(classinfo.cname),
+ mappable_code=mappable_code
+ )
+ self.code_types.write(code)
# register classes in the same order as they have been declared.
# this way, base classes will be registered in Python before their derivatives.
classlist1.sort()
for decl_idx, name, classinfo in classlist1:
- code = classinfo.gen_code(self)
- self.code_types.write(code)
- if not classinfo.ismap:
- self.code_type_reg.write("MKTYPE2(%s);\n" % (classinfo.name,) )
- self.code_type_publish.write("PUBLISH_OBJECT(\"{name}\", pyopencv_{name}_Type);\n".format(name=classinfo.name))
+ if classinfo.ismap:
+ continue
+ self.code_type_publish.write(classinfo.gen_def(self))
+
# step 3: generate the code for all the global functions
for ns_name, ns in sorted(self.namespaces.items()):
code = func.gen_code(self)
self.code_funcs.write(code)
self.gen_namespace(ns_name)
- self.gen_namespaces_reg()
+ self.code_ns_init.write('CVPY_MODULE("{}", {});\n'.format(ns_name[2:], normalize_class_name(ns_name)))
# step 4: generate the code for enum types
enumlist = list(self.enums.values())
self.save(output_path, "pyopencv_generated_include.h", self.code_include)
self.save(output_path, "pyopencv_generated_funcs.h", self.code_funcs)
self.save(output_path, "pyopencv_generated_enums.h", self.code_enums)
- self.save(output_path, "pyopencv_generated_types.h", self.code_types)
- self.save(output_path, "pyopencv_generated_type_reg.h", self.code_type_reg)
- self.save(output_path, "pyopencv_generated_ns_reg.h", self.code_ns_reg)
- self.save(output_path, "pyopencv_generated_type_publish.h", self.code_type_publish)
+ self.save(output_path, "pyopencv_generated_types.h", self.code_type_publish)
+ self.save(output_path, "pyopencv_generated_types_content.h", self.code_types)
+ self.save(output_path, "pyopencv_generated_modules.h", self.code_ns_init)
+ self.save(output_path, "pyopencv_generated_modules_content.h", self.code_ns_reg)
self.save_json(output_path, "pyopencv_signatures.json", self.py_signatures)
if __name__ == "__main__":
#define __PYCOMPAT_HPP__
#if PY_MAJOR_VERSION >= 3
+
// Python3 treats all ints as longs, PyInt_X functions have been removed.
#define PyInt_Check PyLong_Check
#define PyInt_CheckExact PyLong_CheckExact
#define PyInt_FromLong PyLong_FromLong
#define PyNumber_Int PyNumber_Long
-// Python3 strings are unicode, these defines mimic the Python2 functionality.
-#define PyString_Check PyUnicode_Check
+
#define PyString_FromString PyUnicode_FromString
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
-#define PyString_Size PyUnicode_GET_SIZE
-// PyUnicode_AsUTF8 isn't available until Python 3.3
-#if (PY_VERSION_HEX < 0x03030000)
-#define PyString_AsString _PyUnicode_AsString
-#else
-#define PyString_AsString PyUnicode_AsUTF8
+#endif // PY_MAJOR >=3
+
+static inline bool getUnicodeString(PyObject * obj, std::string &str)
+{
+ bool res = false;
+ if (PyUnicode_Check(obj))
+ {
+ PyObject * bytes = PyUnicode_AsUTF8String(obj);
+ if (PyBytes_Check(bytes))
+ {
+ const char * raw = PyBytes_AsString(bytes);
+ if (raw)
+ {
+ str = std::string(raw);
+ res = true;
+ }
+ }
+ Py_XDECREF(bytes);
+ }
+#if PY_MAJOR_VERSION < 3
+ else if (PyString_Check(obj))
+ {
+ const char * raw = PyString_AsString(obj);
+ if (raw)
+ {
+ str = std::string(raw);
+ res = true;
+ }
+ }
#endif
+ return res;
+}
+
+//==================================================================================================
+
+#define CV_PY_FN_WITH_KW_(fn, flags) (PyCFunction)(void*)(PyCFunctionWithKeywords)(fn), (flags) | METH_VARARGS | METH_KEYWORDS
+#define CV_PY_FN_NOARGS_(fn, flags) (PyCFunction)(fn), (flags) | METH_NOARGS
+
+#define CV_PY_FN_WITH_KW(fn) CV_PY_FN_WITH_KW_(fn, 0)
+#define CV_PY_FN_NOARGS(fn) CV_PY_FN_NOARGS_(fn, 0)
+
+#define CV_PY_TO_CLASS(TYPE) \
+template<> \
+bool pyopencv_to(PyObject* dst, TYPE& src, const char* name) \
+{ \
+ if (!dst || dst == Py_None) \
+ return true; \
+ Ptr<TYPE> ptr; \
+ \
+ if (!pyopencv_to(dst, ptr, name)) return false; \
+ src = *ptr; \
+ return true; \
+}
+
+#define CV_PY_FROM_CLASS(TYPE) \
+template<> \
+PyObject* pyopencv_from(const TYPE& src) \
+{ \
+ Ptr<TYPE> ptr(new TYPE()); \
+ \
+ *ptr = src; \
+ return pyopencv_from(ptr); \
+}
+
+#define CV_PY_TO_CLASS_PTR(TYPE) \
+template<> \
+bool pyopencv_to(PyObject* dst, TYPE*& src, const char* name) \
+{ \
+ if (!dst || dst == Py_None) \
+ return true; \
+ Ptr<TYPE> ptr; \
+ \
+ if (!pyopencv_to(dst, ptr, name)) return false; \
+ src = ptr; \
+ return true; \
+}
+
+#define CV_PY_FROM_CLASS_PTR(TYPE) \
+static PyObject* pyopencv_from(TYPE*& src) \
+{ \
+ return pyopencv_from(Ptr<TYPE>(src)); \
+}
+
+#define CV_PY_TO_ENUM(TYPE) \
+template<> \
+bool pyopencv_to(PyObject* dst, TYPE& src, const char* name) \
+{ \
+ if (!dst || dst == Py_None) \
+ return true; \
+ int underlying = 0; \
+ \
+ if (!pyopencv_to(dst, underlying, name)) return false; \
+ src = static_cast<TYPE>(underlying); \
+ return true; \
+}
+
+#define CV_PY_FROM_ENUM(TYPE) \
+template<> \
+PyObject* pyopencv_from(const TYPE& src) \
+{ \
+ return pyopencv_from(static_cast<int>(src)); \
+}
+
+//==================================================================================================
+
+#if PY_MAJOR_VERSION >= 3
+#define CVPY_TYPE_HEAD PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#define CVPY_TYPE_INCREF(T) Py_INCREF(T)
+#else
+#define CVPY_TYPE_HEAD PyObject_HEAD_INIT(&PyType_Type) 0,
+#define CVPY_TYPE_INCREF(T) _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA (T)->ob_refcnt++
#endif
+
+#define CVPY_TYPE_DECLARE(NAME, STORAGE, SNAME) \
+ struct pyopencv_##NAME##_t \
+ { \
+ PyObject_HEAD \
+ STORAGE v; \
+ }; \
+ static PyTypeObject pyopencv_##NAME##_TypeXXX = \
+ { \
+ CVPY_TYPE_HEAD \
+ MODULESTR"."#NAME, \
+ sizeof(pyopencv_##NAME##_t), \
+ }; \
+ static PyTypeObject * pyopencv_##NAME##_TypePtr = &pyopencv_##NAME##_TypeXXX; \
+ static bool pyopencv_##NAME##_getp(PyObject * self, STORAGE * & dst) \
+ { \
+ if (PyObject_TypeCheck(self, pyopencv_##NAME##_TypePtr)) \
+ { \
+ dst = &(((pyopencv_##NAME##_t*)self)->v); \
+ return true; \
+ } \
+ return false; \
+ } \
+ static PyObject * pyopencv_##NAME##_Instance(const STORAGE &r) \
+ { \
+ pyopencv_##NAME##_t *m = PyObject_NEW(pyopencv_##NAME##_t, pyopencv_##NAME##_TypePtr); \
+ new (&(m->v)) STORAGE(r); \
+ return (PyObject*)m; \
+ } \
+ static void pyopencv_##NAME##_dealloc(PyObject* self) \
+ { \
+ ((pyopencv_##NAME##_t*)self)->v.STORAGE::~SNAME(); \
+ PyObject_Del(self); \
+ } \
+ static PyObject* pyopencv_##NAME##_repr(PyObject* self) \
+ { \
+ char str[1000]; \
+ sprintf(str, "<"#NAME" %p>", self); \
+ return PyString_FromString(str); \
+ }
+
+
+#define CVPY_TYPE_INIT_STATIC(NAME, ERROR_HANDLER, BASE, CONSTRUCTOR) \
+ { \
+ pyopencv_##NAME##_TypePtr->tp_base = pyopencv_##BASE##_TypePtr; \
+ pyopencv_##NAME##_TypePtr->tp_dealloc = pyopencv_##NAME##_dealloc; \
+ pyopencv_##NAME##_TypePtr->tp_repr = pyopencv_##NAME##_repr; \
+ pyopencv_##NAME##_TypePtr->tp_getset = pyopencv_##NAME##_getseters; \
+ pyopencv_##NAME##_TypePtr->tp_init = (initproc) CONSTRUCTOR; \
+ pyopencv_##NAME##_TypePtr->tp_methods = pyopencv_##NAME##_methods; \
+ pyopencv_##NAME##_TypePtr->tp_alloc = PyType_GenericAlloc; \
+ pyopencv_##NAME##_TypePtr->tp_new = PyType_GenericNew; \
+ pyopencv_##NAME##_TypePtr->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; \
+ if (PyType_Ready(pyopencv_##NAME##_TypePtr) != 0) \
+ { \
+ ERROR_HANDLER; \
+ } \
+ CVPY_TYPE_INCREF(pyopencv_##NAME##_TypePtr); \
+ PyModule_AddObject(m, #NAME, (PyObject *)pyopencv_##NAME##_TypePtr); \
+ }
+
+//==================================================================================================
+
+#define CVPY_TYPE_DECLARE_DYNAMIC(NAME, STORAGE, SNAME) \
+ struct pyopencv_##NAME##_t \
+ { \
+ PyObject_HEAD \
+ STORAGE v; \
+ }; \
+ static PyObject * pyopencv_##NAME##_TypePtr = 0; \
+ static bool pyopencv_##NAME##_getp(PyObject * self, STORAGE * & dst) \
+ { \
+ if (PyObject_TypeCheck(self, (PyTypeObject*)pyopencv_##NAME##_TypePtr)) \
+ { \
+ dst = &(((pyopencv_##NAME##_t*)self)->v); \
+ return true; \
+ } \
+ return false; \
+ } \
+ static PyObject * pyopencv_##NAME##_Instance(const STORAGE &r) \
+ { \
+ pyopencv_##NAME##_t *m = PyObject_New(pyopencv_##NAME##_t, (PyTypeObject*)pyopencv_##NAME##_TypePtr); \
+ new (&(m->v)) STORAGE(r); \
+ return (PyObject*)m; \
+ } \
+ static void pyopencv_##NAME##_dealloc(PyObject* self) \
+ { \
+ ((pyopencv_##NAME##_t*)self)->v.STORAGE::~SNAME(); \
+ PyObject_Del(self); \
+ } \
+ static PyObject* pyopencv_##NAME##_repr(PyObject* self) \
+ { \
+ char str[1000]; \
+ sprintf(str, "<"#NAME" %p>", self); \
+ return PyString_FromString(str); \
+ } \
+ static PyType_Slot pyopencv_##NAME##_Slots[] = \
+ { \
+ {Py_tp_dealloc, 0}, \
+ {Py_tp_repr, 0}, \
+ {Py_tp_getset, 0}, \
+ {Py_tp_init, 0}, \
+ {Py_tp_methods, 0}, \
+ {Py_tp_alloc, 0}, \
+ {Py_tp_new, 0}, \
+ {0, 0} \
+ }; \
+ static PyType_Spec pyopencv_##NAME##_Spec = \
+ { \
+ MODULESTR"."#NAME, \
+ sizeof(pyopencv_##NAME##_t), \
+ 0, \
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, \
+ pyopencv_##NAME##_Slots \
+ };
+
+#define CVPY_TYPE_INIT_DYNAMIC(NAME, ERROR_HANDLER, BASE, CONSTRUCTOR) \
+ { \
+ pyopencv_##NAME##_Slots[0].pfunc /*tp_dealloc*/ = (void*)pyopencv_##NAME##_dealloc; \
+ pyopencv_##NAME##_Slots[1].pfunc /*tp_repr*/ = (void*)pyopencv_##NAME##_repr; \
+ pyopencv_##NAME##_Slots[2].pfunc /*tp_getset*/ = (void*)pyopencv_##NAME##_getseters; \
+ pyopencv_##NAME##_Slots[3].pfunc /*tp_init*/ = (void*) CONSTRUCTOR; \
+ pyopencv_##NAME##_Slots[4].pfunc /*tp_methods*/ = pyopencv_##NAME##_methods; \
+ pyopencv_##NAME##_Slots[5].pfunc /*tp_alloc*/ = (void*)PyType_GenericAlloc; \
+ pyopencv_##NAME##_Slots[6].pfunc /*tp_new*/ = (void*)PyType_GenericNew; \
+ PyObject * bases = 0; \
+ if (pyopencv_##BASE##_TypePtr) \
+ bases = PyTuple_Pack(1, pyopencv_##BASE##_TypePtr); \
+ pyopencv_##NAME##_TypePtr = PyType_FromSpecWithBases(&pyopencv_##NAME##_Spec, bases); \
+ if (!pyopencv_##NAME##_TypePtr) \
+ { \
+ printf("Failed to init: " #NAME ", base (" #BASE ")" "\n"); \
+ ERROR_HANDLER; \
+ } \
+ PyModule_AddObject(m, #NAME, (PyObject *)pyopencv_##NAME##_TypePtr); \
+ }
+
+// Debug module load:
+//
+// else \
+// { \
+// printf("Init: " #NAME ", base (" #BASE ") -> %p" "\n", pyopencv_##NAME##_TypePtr); \
+// } \
+
+
#endif // END HEADER GUARD