提交 b3e6c97d 编写于 作者: A Alexander Alekhin

Merge pull request #14736 from mshabunin:minimal-python-3

......@@ -21,16 +21,19 @@ bool pyopencv_to(PyObject *o, dnn::DictValue &dv, const char *name)
}
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<>
......@@ -134,7 +137,7 @@ public:
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);
......
......@@ -27,20 +27,20 @@ bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name)
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);
......@@ -56,8 +56,13 @@ bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name)
}
else
{
ok = false;
break;
std::string val_str;
if (!getUnicodeString(item, val_str))
{
ok = false;
break;
}
p.setString(k, val_str);
}
}
}
......@@ -79,4 +84,4 @@ bool pyopencv_to(PyObject *o, cvflann::flann_distance_t& dist, const char *name)
dist = (cvflann::flann_distance_t)d;
return ok;
}
#endif
\ No newline at end of file
#endif
......@@ -51,11 +51,13 @@ if(NOT HAVE_CUDA)
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}"
)
......
......@@ -24,6 +24,22 @@ if(TARGET gen_opencv_python_source)
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)
......@@ -54,6 +70,13 @@ else()
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}")
......@@ -111,9 +134,6 @@ else()
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/")
......
......@@ -2,6 +2,14 @@ if(NOT PYTHON3_INCLUDE_PATH OR NOT PYTHON3_NUMPY_INCLUDE_DIRS)
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)
......
此差异已折叠。
......@@ -16,20 +16,12 @@ ignored_arg_types = ["RNG*"]
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) """)
......@@ -50,53 +42,6 @@ gen_template_func_body = Template("""$code_decl
}
""")
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;
......@@ -108,43 +53,23 @@ gen_template_mappable = Template("""
""")
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}
......@@ -153,10 +78,11 @@ struct PyOpenCV_Converter< Ptr<${cname}> >
}
};
""" % 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("""
......@@ -169,37 +95,26 @@ 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}
}
""")
......@@ -373,20 +288,29 @@ class ClassInfo(object):
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):
......@@ -634,7 +558,7 @@ class FuncInfo(object):
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
......@@ -642,14 +566,13 @@ class FuncInfo(object):
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 = []
......@@ -871,8 +794,8 @@ class PythonWrapperGenerator(object):
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
......@@ -1013,14 +936,6 @@ class PythonWrapperGenerator(object):
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
......@@ -1113,18 +1028,22 @@ class PythonWrapperGenerator(object):
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.
......@@ -1132,11 +1051,10 @@ class PythonWrapperGenerator(object):
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()):
......@@ -1148,7 +1066,7 @@ class PythonWrapperGenerator(object):
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())
......@@ -1166,10 +1084,10 @@ class PythonWrapperGenerator(object):
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__":
......
......@@ -45,6 +45,7 @@
#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
......@@ -53,18 +54,266 @@
#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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册