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

bindings: backport generator from OpenCV 4.x

- better handling of enum arguments
- less merge conflicts
上级 d034ef6f
#ifdef HAVE_OPENCV_CORE
#include "opencv2/core/mat.hpp"
typedef std::vector<Range> vector_Range;
CV_PY_TO_CLASS(UMat);
CV_PY_FROM_CLASS(UMat);
static bool cv_mappable_to(const Ptr<Mat>& src, Ptr<UMat>& dst)
{
//dst.reset(new UMat(src->getUMat(ACCESS_RW)));
dst.reset(new UMat());
src->copyTo(*dst);
return true;
}
static void* cv_UMat_queue()
{
return cv::ocl::Queue::getDefault().ptr();
}
static void* cv_UMat_context()
{
return cv::ocl::Context::getDefault().ptr();
}
static Mat cv_UMat_get(const UMat* _self)
{
Mat m;
m.allocator = &g_numpyAllocator;
_self->copyTo(m);
return m;
}
#endif
#error This is a shadow header file, which is not intended for processing by any compiler. \
Only bindings parser should handle this file.
namespace cv
{
class CV_EXPORTS_W UMat
{
public:
//! default constructor
CV_WRAP UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! constructs 2D matrix of the specified size and type
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
CV_WRAP UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
CV_WRAP UMat(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! constucts 2D matrix and fills it with the specified value _s.
CV_WRAP UMat(int rows, int cols, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
CV_WRAP UMat(Size size, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! Mat is mappable to UMat
CV_WRAP_MAPPABLE(Ptr<Mat>);
//! returns the OpenCL queue used by OpenCV UMat
CV_WRAP_PHANTOM(static void* queue());
//! returns the OpenCL context used by OpenCV UMat
CV_WRAP_PHANTOM(static void* context());
//! copy constructor
CV_WRAP UMat(const UMat& m);
//! creates a matrix header for a part of the bigger matrix
CV_WRAP UMat(const UMat& m, const Range& rowRange, const Range& colRange = Range::all());
CV_WRAP UMat(const UMat& m, const Rect& roi);
CV_WRAP UMat(const UMat& m, const std::vector<Range>& ranges);
//CV_WRAP_AS(get) Mat getMat(int flags CV_WRAP_DEFAULT(ACCESS_RW)) const;
//! returns a numpy matrix
CV_WRAP_PHANTOM(Mat get() const);
//! returns true iff the matrix data is continuous
// (i.e. when there are no gaps between successive rows).
// similar to CV_IS_MAT_CONT(cvmat->type)
CV_WRAP bool isContinuous() const;
//! returns true if the matrix is a submatrix of another matrix
CV_WRAP bool isSubmatrix() const;
/*! Returns the OpenCL buffer handle on which UMat operates on.
The UMat instance should be kept alive during the use of the handle to prevent the buffer to be
returned to the OpenCV buffer pool.
*/
CV_WRAP void* handle(int/*AccessFlag*/ accessFlags) const;
// offset of the submatrix (or 0)
CV_PROP_RW size_t offset;
};
} // namespace cv
...@@ -140,17 +140,18 @@ class GeneralInfo(): ...@@ -140,17 +140,18 @@ class GeneralInfo():
def fullName(self, isCPP=False): def fullName(self, isCPP=False):
result = ".".join([self.fullClass(), self.name]) result = ".".join([self.fullClass(), self.name])
return result if not isCPP else result.replace(".", "::") return result if not isCPP else get_cname(result)
def fullClass(self, isCPP=False): def fullClass(self, isCPP=False):
result = ".".join([f for f in [self.namespace] + self.classpath.split(".") if len(f)>0]) result = ".".join([f for f in [self.namespace] + self.classpath.split(".") if len(f)>0])
return result if not isCPP else result.replace(".", "::") return result if not isCPP else get_cname(result)
class ConstInfo(GeneralInfo): class ConstInfo(GeneralInfo):
def __init__(self, decl, addedManually=False, namespaces=[]): def __init__(self, decl, addedManually=False, namespaces=[], enumType=None):
GeneralInfo.__init__(self, "const", decl, namespaces) GeneralInfo.__init__(self, "const", decl, namespaces)
self.cname = self.name.replace(".", "::") self.cname = get_cname(self.name)
self.value = decl[1] self.value = decl[1]
self.enumType = enumType
self.addedManually = addedManually self.addedManually = addedManually
if self.namespace in namespaces_dict: if self.namespace in namespaces_dict:
self.name = '%s_%s' % (namespaces_dict[self.namespace], self.name) self.name = '%s_%s' % (namespaces_dict[self.namespace], self.name)
...@@ -166,6 +167,25 @@ class ConstInfo(GeneralInfo): ...@@ -166,6 +167,25 @@ class ConstInfo(GeneralInfo):
return True return True
return False return False
def normalize_field_name(name):
return name.replace(".","_").replace("[","").replace("]","").replace("_getNativeObjAddr()","_nativeObj")
def normalize_class_name(name):
return re.sub(r"^cv\.", "", name).replace(".", "_")
def get_cname(name):
return name.replace(".", "::")
def cast_from(t):
if t in type_dict and "cast_from" in type_dict[t]:
return type_dict[t]["cast_from"]
return t
def cast_to(t):
if t in type_dict and "cast_to" in type_dict[t]:
return type_dict[t]["cast_to"]
return t
class ClassPropInfo(): class ClassPropInfo():
def __init__(self, decl): # [f_ctype, f_name, '', '/RW'] def __init__(self, decl): # [f_ctype, f_name, '', '/RW']
self.ctype = decl[0] self.ctype = decl[0]
...@@ -178,7 +198,7 @@ class ClassPropInfo(): ...@@ -178,7 +198,7 @@ class ClassPropInfo():
class ClassInfo(GeneralInfo): class ClassInfo(GeneralInfo):
def __init__(self, decl, namespaces=[]): # [ 'class/struct cname', ': base', [modlist] ] def __init__(self, decl, namespaces=[]): # [ 'class/struct cname', ': base', [modlist] ]
GeneralInfo.__init__(self, "class", decl, namespaces) GeneralInfo.__init__(self, "class", decl, namespaces)
self.cname = self.name.replace(".", "::") self.cname = get_cname(self.name)
self.methods = [] self.methods = []
self.methods_suffixes = {} self.methods_suffixes = {}
self.consts = [] # using a list to save the occurrence order self.consts = [] # using a list to save the occurrence order
...@@ -303,7 +323,7 @@ class ArgInfo(): ...@@ -303,7 +323,7 @@ class ArgInfo():
class FuncInfo(GeneralInfo): class FuncInfo(GeneralInfo):
def __init__(self, decl, namespaces=[]): # [ funcname, return_ctype, [modifiers], [args] ] def __init__(self, decl, namespaces=[]): # [ funcname, return_ctype, [modifiers], [args] ]
GeneralInfo.__init__(self, "func", decl, namespaces) GeneralInfo.__init__(self, "func", decl, namespaces)
self.cname = decl[0].replace(".", "::") self.cname = get_cname(decl[0])
self.jname = self.name self.jname = self.name
self.isconstructor = self.name == self.classname self.isconstructor = self.name == self.classname
if "[" in self.name: if "[" in self.name:
...@@ -403,13 +423,16 @@ class JavaWrapperGenerator(object): ...@@ -403,13 +423,16 @@ class JavaWrapperGenerator(object):
) )
logging.info('ok: class %s, name: %s, base: %s', classinfo, name, classinfo.base) logging.info('ok: class %s, name: %s, base: %s', classinfo, name, classinfo.base)
def add_const(self, decl): # [ "const cname", val, [], [] ] def add_const(self, decl, enumType=None): # [ "const cname", val, [], [] ]
constinfo = ConstInfo(decl, namespaces=self.namespaces) constinfo = ConstInfo(decl, namespaces=self.namespaces, enumType=enumType)
if constinfo.isIgnored(): if constinfo.isIgnored():
logging.info('ignored: %s', constinfo) logging.info('ignored: %s', constinfo)
elif not self.isWrapped(constinfo.classname):
logging.info('class not found: %s', constinfo)
else: else:
if not self.isWrapped(constinfo.classname):
logging.info('class not found: %s', constinfo)
constinfo.name = constinfo.classname + '_' + constinfo.name
constinfo.classname = ''
ci = self.getClass(constinfo.classname) ci = self.getClass(constinfo.classname)
duplicate = ci.getConst(constinfo.name) duplicate = ci.getConst(constinfo.name)
if duplicate: if duplicate:
...@@ -421,6 +444,18 @@ class JavaWrapperGenerator(object): ...@@ -421,6 +444,18 @@ class JavaWrapperGenerator(object):
ci.addConst(constinfo) ci.addConst(constinfo)
logging.info('ok: %s', constinfo) logging.info('ok: %s', constinfo)
def add_enum(self, decl): # [ "enum cname", "", [], [] ]
enumType = decl[0].rsplit(" ", 1)[1]
if enumType.endswith("<unnamed>"):
enumType = None
else:
ctype = normalize_class_name(enumType)
type_dict[ctype] = { "cast_from" : "int", "cast_to" : get_cname(enumType), "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" }
const_decls = decl[3]
for decl in const_decls:
self.add_const(decl, enumType)
def add_func(self, decl): def add_func(self, decl):
fi = FuncInfo(decl, namespaces=self.namespaces) fi = FuncInfo(decl, namespaces=self.namespaces)
classname = fi.classname or self.Module classname = fi.classname or self.Module
...@@ -479,6 +514,9 @@ class JavaWrapperGenerator(object): ...@@ -479,6 +514,9 @@ class JavaWrapperGenerator(object):
self.add_class(decl) self.add_class(decl)
elif name.startswith("const"): elif name.startswith("const"):
self.add_const(decl) self.add_const(decl)
elif name.startswith("enum"):
# enum
self.add_enum(decl)
else: # function else: # function
self.add_func(decl) self.add_func(decl)
...@@ -518,7 +556,7 @@ class JavaWrapperGenerator(object): ...@@ -518,7 +556,7 @@ class JavaWrapperGenerator(object):
if self.isWrapped(t): if self.isWrapped(t):
return self.getClass(t).fullName(isCPP=True) return self.getClass(t).fullName(isCPP=True)
else: else:
return t return cast_from(t)
def gen_func(self, ci, fi, prop_name=''): def gen_func(self, ci, fi, prop_name=''):
logging.info("%s", fi) logging.info("%s", fi)
...@@ -551,7 +589,7 @@ class JavaWrapperGenerator(object): ...@@ -551,7 +589,7 @@ class JavaWrapperGenerator(object):
msg = "// Return type '%s' is not supported, skipping the function\n\n" % fi.ctype msg = "// Return type '%s' is not supported, skipping the function\n\n" % fi.ctype
self.skipped_func_list.append(c_decl + "\n" + msg) self.skipped_func_list.append(c_decl + "\n" + msg)
j_code.write( " "*4 + msg ) j_code.write( " "*4 + msg )
logging.warning("SKIP:" + c_decl.strip() + "\t due to RET type" + fi.ctype) logging.warning("SKIP:" + c_decl.strip() + "\t due to RET type " + fi.ctype)
return return
for a in fi.args: for a in fi.args:
if a.ctype not in type_dict: if a.ctype not in type_dict:
...@@ -563,7 +601,7 @@ class JavaWrapperGenerator(object): ...@@ -563,7 +601,7 @@ class JavaWrapperGenerator(object):
msg = "// Unknown type '%s' (%s), skipping the function\n\n" % (a.ctype, a.out or "I") msg = "// Unknown type '%s' (%s), skipping the function\n\n" % (a.ctype, a.out or "I")
self.skipped_func_list.append(c_decl + "\n" + msg) self.skipped_func_list.append(c_decl + "\n" + msg)
j_code.write( " "*4 + msg ) j_code.write( " "*4 + msg )
logging.warning("SKIP:" + c_decl.strip() + "\t due to ARG type" + a.ctype + "/" + (a.out or "I")) logging.warning("SKIP:" + c_decl.strip() + "\t due to ARG type " + a.ctype + "/" + (a.out or "I"))
return return
self.ported_func_list.append(c_decl) self.ported_func_list.append(c_decl)
...@@ -642,7 +680,7 @@ class JavaWrapperGenerator(object): ...@@ -642,7 +680,7 @@ class JavaWrapperGenerator(object):
if "I" in a.out or not a.out or self.isWrapped(a.ctype): # input arg, pass by primitive fields if "I" in a.out or not a.out or self.isWrapped(a.ctype): # input arg, pass by primitive fields
for f in fields: for f in fields:
jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) ) jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) )
jni_args.append( ArgInfo([ f[0], a.name + f[1].replace(".","_").replace("[","").replace("]","").replace("_getNativeObjAddr()","_nativeObj"), "", [], "" ]) ) jni_args.append( ArgInfo([ f[0], a.name + normalize_field_name(f[1]), "", [], "" ]) )
if "O" in a.out and not self.isWrapped(a.ctype): # out arg, pass as double[] if "O" in a.out and not self.isWrapped(a.ctype): # out arg, pass as double[]
jn_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) ) jn_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
jni_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) ) jni_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
...@@ -690,7 +728,7 @@ class JavaWrapperGenerator(object): ...@@ -690,7 +728,7 @@ class JavaWrapperGenerator(object):
" private static native $type $name($args);\n").substitute(\ " private static native $type $name($args);\n").substitute(\
type = type_dict[fi.ctype].get("jn_type", "double[]"), \ type = type_dict[fi.ctype].get("jn_type", "double[]"), \
name = fi.jname + '_' + str(suffix_counter), \ name = fi.jname + '_' + str(suffix_counter), \
args = ", ".join(["%s %s" % (type_dict[a.ctype]["jn_type"], a.name.replace(".","_").replace("[","").replace("]","").replace("_getNativeObjAddr()","_nativeObj")) for a in jn_args]) args = ", ".join(["%s %s" % (type_dict[a.ctype]["jn_type"], normalize_field_name(a.name)) for a in jn_args])
) ); ) );
# java part: # java part:
...@@ -848,7 +886,7 @@ class JavaWrapperGenerator(object): ...@@ -848,7 +886,7 @@ class JavaWrapperGenerator(object):
if not a.out and not "jni_var" in type_dict[a.ctype]: if not a.out and not "jni_var" in type_dict[a.ctype]:
# explicit cast to C type to avoid ambiguous call error on platforms (mingw) # explicit cast to C type to avoid ambiguous call error on platforms (mingw)
# where jni types are different from native types (e.g. jint is not the same as int) # where jni types are different from native types (e.g. jint is not the same as int)
jni_name = "(%s)%s" % (a.ctype, jni_name) jni_name = "(%s)%s" % (cast_to(a.ctype), jni_name)
if not a.ctype: # hidden if not a.ctype: # hidden
jni_name = a.defval jni_name = a.defval
cvargs.append( type_dict[a.ctype].get("jni_name", jni_name) % {"n" : a.name}) cvargs.append( type_dict[a.ctype].get("jni_name", jni_name) % {"n" : a.name})
...@@ -922,10 +960,34 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname ...@@ -922,10 +960,34 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname
%s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.private_consts]) %s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.private_consts])
) )
if ci.consts: if ci.consts:
logging.info("%s", ci.consts) enumTypes = set(map(lambda c: c.enumType, ci.consts))
grouped_consts = {enumType: [c for c in ci.consts if c.enumType == enumType] for enumType in enumTypes}
for typeName, consts in grouped_consts.items():
logging.info("%s", consts)
if typeName:
typeName = typeName.rsplit(".", 1)[-1]
###################### Utilize Java enums ######################
# ci.j_code.write("""
# public enum {1} {{
# {0};
#
# private final int id;
# {1}(int id) {{ this.id = id; }}
# {1}({1} _this) {{ this.id = _this.id; }}
# public int getValue() {{ return id; }}
# }}\n\n""".format((",\n"+" "*8).join(["%s(%s)" % (c.name, c.value) for c in consts]), typeName)
# )
################################################################
ci.j_code.write("""
// C++: enum {1}
public static final int
{0};\n\n""".format((",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in consts]), typeName)
)
else:
ci.j_code.write(""" ci.j_code.write("""
// C++: enum <unnamed>
public static final int public static final int
%s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.consts]) {0};\n\n""".format((",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in consts]))
) )
# methods # methods
for fi in ci.getAllMethods(): for fi in ci.getAllMethods():
...@@ -1123,7 +1185,7 @@ if __name__ == "__main__": ...@@ -1123,7 +1185,7 @@ if __name__ == "__main__":
with open(srcfiles_fname) as f: with open(srcfiles_fname) as f:
srcfiles = [os.path.join(module_location, str(l).strip()) for l in f.readlines() if str(l).strip()] srcfiles = [os.path.join(module_location, str(l).strip()) for l in f.readlines() if str(l).strip()]
else: else:
re_bad = re.compile(r'(private|.inl.hpp$|_inl.hpp$|.details.hpp$|_winrt.hpp$|/cuda/)') re_bad = re.compile(r'(private|.inl.hpp$|_inl.hpp$|.details.hpp$|_winrt.hpp$|/cuda/|/legacy/)')
# .h files before .hpp # .h files before .hpp
h_files = [] h_files = []
hpp_files = [] hpp_files = []
......
...@@ -26,15 +26,15 @@ foreach(m ${OPENCV_PYTHON_MODULES}) ...@@ -26,15 +26,15 @@ foreach(m ${OPENCV_PYTHON_MODULES})
list(APPEND opencv_hdrs "${hdr}") list(APPEND opencv_hdrs "${hdr}")
endif() endif()
endforeach() endforeach()
file(GLOB hdr ${OPENCV_MODULE_${m}_LOCATION}/misc/python/shadow*.hpp)
list(APPEND opencv_hdrs ${hdr})
file(GLOB userdef_hdrs ${OPENCV_MODULE_${m}_LOCATION}/misc/python/pyopencv*.hpp) file(GLOB userdef_hdrs ${OPENCV_MODULE_${m}_LOCATION}/misc/python/pyopencv*.hpp)
list(APPEND opencv_userdef_hdrs ${userdef_hdrs}) list(APPEND opencv_userdef_hdrs ${userdef_hdrs})
endforeach(m) endforeach(m)
# header blacklist # header blacklist
ocv_list_filterout(opencv_hdrs "modules/.*\\\\.h$") ocv_list_filterout(opencv_hdrs "modules/.*\\\\.h$")
ocv_list_filterout(opencv_hdrs "modules/core/.*/cuda") ocv_list_filterout(opencv_hdrs "modules/core/.*/cuda/")
ocv_list_filterout(opencv_hdrs "modules/cuda.*")
ocv_list_filterout(opencv_hdrs "modules/cudev")
ocv_list_filterout(opencv_hdrs "modules/core/.*/hal/") ocv_list_filterout(opencv_hdrs "modules/core/.*/hal/")
ocv_list_filterout(opencv_hdrs "modules/core/.*/opencl/") ocv_list_filterout(opencv_hdrs "modules/core/.*/opencl/")
ocv_list_filterout(opencv_hdrs "modules/.+/utils/.*") ocv_list_filterout(opencv_hdrs "modules/.+/utils/.*")
...@@ -43,7 +43,12 @@ ocv_list_filterout(opencv_hdrs "modules/.*_inl\\\\.h*") ...@@ -43,7 +43,12 @@ ocv_list_filterout(opencv_hdrs "modules/.*_inl\\\\.h*")
ocv_list_filterout(opencv_hdrs "modules/.*\\\\.details\\\\.h*") ocv_list_filterout(opencv_hdrs "modules/.*\\\\.details\\\\.h*")
ocv_list_filterout(opencv_hdrs "modules/.*\\\\.private\\\\.h*") ocv_list_filterout(opencv_hdrs "modules/.*\\\\.private\\\\.h*")
ocv_list_filterout(opencv_hdrs "modules/.*/private\\\\.h*") ocv_list_filterout(opencv_hdrs "modules/.*/private\\\\.h*")
ocv_list_filterout(opencv_hdrs "modules/.*/legacy/.*")
ocv_list_filterout(opencv_hdrs "modules/.*/detection_based_tracker\\\\.hpp") # Conditional compilation ocv_list_filterout(opencv_hdrs "modules/.*/detection_based_tracker\\\\.hpp") # Conditional compilation
if(NOT HAVE_CUDA)
ocv_list_filterout(opencv_hdrs "modules/cuda.*")
ocv_list_filterout(opencv_hdrs "modules/cudev")
endif()
set(cv2_generated_files set(cv2_generated_files
"${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h" "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h"
......
此差异已折叠。
此差异已折叠。
...@@ -6,6 +6,7 @@ import os, sys, re, string, io ...@@ -6,6 +6,7 @@ import os, sys, re, string, io
# the list only for debugging. The real list, used in the real OpenCV build, is specified in CMakeLists.txt # the list only for debugging. The real list, used in the real OpenCV build, is specified in CMakeLists.txt
opencv_hdr_list = [ opencv_hdr_list = [
"../../core/include/opencv2/core.hpp", "../../core/include/opencv2/core.hpp",
"../../core/include/opencv2/core/mat.hpp",
"../../core/include/opencv2/core/ocl.hpp", "../../core/include/opencv2/core/ocl.hpp",
"../../flann/include/opencv2/flann/miniflann.hpp", "../../flann/include/opencv2/flann/miniflann.hpp",
"../../ml/include/opencv2/ml.hpp", "../../ml/include/opencv2/ml.hpp",
...@@ -32,8 +33,9 @@ original_return_type is None if the original_return_type is the same as return_v ...@@ -32,8 +33,9 @@ original_return_type is None if the original_return_type is the same as return_v
class CppHeaderParser(object): class CppHeaderParser(object):
def __init__(self, generate_umat_decls=False): def __init__(self, generate_umat_decls=False, generate_gpumat_decls=False):
self._generate_umat_decls = generate_umat_decls self._generate_umat_decls = generate_umat_decls
self._generate_gpumat_decls = generate_gpumat_decls
self.BLOCK_TYPE = 0 self.BLOCK_TYPE = 0
self.BLOCK_NAME = 1 self.BLOCK_NAME = 1
...@@ -375,11 +377,9 @@ class CppHeaderParser(object): ...@@ -375,11 +377,9 @@ class CppHeaderParser(object):
decl[2].append("/A") decl[2].append("/A")
if bool(re.match(r".*\)\s*const(\s*=\s*0)?", decl_str)): if bool(re.match(r".*\)\s*const(\s*=\s*0)?", decl_str)):
decl[2].append("/C") decl[2].append("/C")
if "virtual" in decl_str:
print(decl_str)
return decl return decl
def parse_func_decl(self, decl_str, use_umat=False, docstring=""): def parse_func_decl(self, decl_str, mat="Mat", docstring=""):
""" """
Parses the function or method declaration in the form: Parses the function or method declaration in the form:
[([CV_EXPORTS] <rettype>) | CVAPI(rettype)] [([CV_EXPORTS] <rettype>) | CVAPI(rettype)]
...@@ -392,8 +392,7 @@ class CppHeaderParser(object): ...@@ -392,8 +392,7 @@ class CppHeaderParser(object):
""" """
if self.wrap_mode: if self.wrap_mode:
if not (("CV_EXPORTS_AS" in decl_str) or ("CV_EXPORTS_W" in decl_str) or \ if not (("CV_EXPORTS_AS" in decl_str) or ("CV_EXPORTS_W" in decl_str) or ("CV_WRAP" in decl_str)):
("CV_WRAP" in decl_str) or ("CV_WRAP_AS" in decl_str)):
return [] return []
# ignore old API in the documentation check (for now) # ignore old API in the documentation check (for now)
...@@ -413,6 +412,16 @@ class CppHeaderParser(object): ...@@ -413,6 +412,16 @@ class CppHeaderParser(object):
arg, npos3 = self.get_macro_arg(decl_str, npos) arg, npos3 = self.get_macro_arg(decl_str, npos)
func_modlist.append("="+arg) func_modlist.append("="+arg)
decl_str = decl_str[:npos] + decl_str[npos3+1:] decl_str = decl_str[:npos] + decl_str[npos3+1:]
npos = decl_str.find("CV_WRAP_PHANTOM")
if npos >= 0:
decl_str, _ = self.get_macro_arg(decl_str, npos)
func_modlist.append("/phantom")
npos = decl_str.find("CV_WRAP_MAPPABLE")
if npos >= 0:
mappable, npos3 = self.get_macro_arg(decl_str, npos)
func_modlist.append("/mappable="+mappable)
classname = top[1]
return ['.'.join([classname, classname]), None, func_modlist, [], None, None]
virtual_method = False virtual_method = False
pure_virtual_method = False pure_virtual_method = False
...@@ -526,8 +535,6 @@ class CppHeaderParser(object): ...@@ -526,8 +535,6 @@ class CppHeaderParser(object):
t, npos = self.find_next_token(decl_str, ["(", ")", ",", "<", ">"], npos) t, npos = self.find_next_token(decl_str, ["(", ")", ",", "<", ">"], npos)
if not t: if not t:
print("Error: no closing ')' at %d" % (self.lineno,)) print("Error: no closing ')' at %d" % (self.lineno,))
print(decl_str)
print(decl_str[arg_start:])
sys.exit(-1) sys.exit(-1)
if t == "<": if t == "<":
angle_balance += 1 angle_balance += 1
...@@ -563,8 +570,6 @@ class CppHeaderParser(object): ...@@ -563,8 +570,6 @@ class CppHeaderParser(object):
a = a[:eqpos].strip() a = a[:eqpos].strip()
arg_type, arg_name, modlist, argno = self.parse_arg(a, argno) arg_type, arg_name, modlist, argno = self.parse_arg(a, argno)
if self.wrap_mode: if self.wrap_mode:
mat = "UMat" if use_umat else "Mat"
# TODO: Vectors should contain UMat, but this is not very easy to support and not very needed # TODO: Vectors should contain UMat, but this is not very easy to support and not very needed
vector_mat = "vector_{}".format("Mat") vector_mat = "vector_{}".format("Mat")
vector_mat_template = "vector<{}>".format("Mat") vector_mat_template = "vector<{}>".format("Mat")
...@@ -629,8 +634,10 @@ class CppHeaderParser(object): ...@@ -629,8 +634,10 @@ class CppHeaderParser(object):
block_type, block_name = b[self.BLOCK_TYPE], b[self.BLOCK_NAME] block_type, block_name = b[self.BLOCK_TYPE], b[self.BLOCK_NAME]
if block_type in ["file", "enum"]: if block_type in ["file", "enum"]:
continue continue
if block_type not in ["struct", "class", "namespace"]: if block_type in ["enum struct", "enum class"] and block_name == name:
print("Error at %d: there are non-valid entries in the current block stack " % (self.lineno, self.block_stack)) continue
if block_type not in ["struct", "class", "namespace", "enum struct", "enum class"]:
print("Error at %d: there are non-valid entries in the current block stack %s" % (self.lineno, self.block_stack))
sys.exit(-1) sys.exit(-1)
if block_name and (block_type == "namespace" or not qualified_name): if block_name and (block_type == "namespace" or not qualified_name):
n += block_name + "." n += block_name + "."
...@@ -639,7 +646,7 @@ class CppHeaderParser(object): ...@@ -639,7 +646,7 @@ class CppHeaderParser(object):
n = "cv.Algorithm" n = "cv.Algorithm"
return n return n
def parse_stmt(self, stmt, end_token, use_umat=False, docstring=""): def parse_stmt(self, stmt, end_token, mat="Mat", docstring=""):
""" """
parses the statement (ending with ';' or '}') or a block head (ending with '{') parses the statement (ending with ';' or '}') or a block head (ending with '{')
...@@ -706,20 +713,19 @@ class CppHeaderParser(object): ...@@ -706,20 +713,19 @@ class CppHeaderParser(object):
decl[1] = ": " + ", ".join([self.get_dotted_name(b).replace(".","::") for b in bases]) decl[1] = ": " + ", ".join([self.get_dotted_name(b).replace(".","::") for b in bases])
return stmt_type, classname, True, decl return stmt_type, classname, True, decl
if stmt.startswith("enum"): if stmt.startswith("enum") or stmt.startswith("namespace"):
return "enum", "", True, None stmt_list = stmt.rsplit(" ", 1)
if stmt.startswith("namespace"):
stmt_list = stmt.split()
if len(stmt_list) < 2: if len(stmt_list) < 2:
stmt_list.append("<unnamed>") stmt_list.append("<unnamed>")
return stmt_list[0], stmt_list[1], True, None return stmt_list[0], stmt_list[1], True, None
if stmt.startswith("extern") and "\"C\"" in stmt: if stmt.startswith("extern") and "\"C\"" in stmt:
return "namespace", "", True, None return "namespace", "", True, None
if end_token == "}" and context == "enum": if end_token == "}" and context.startswith("enum"):
decl = self.parse_enum(stmt) decl = self.parse_enum(stmt)
return "enum", "", False, decl name = stack_top[self.BLOCK_NAME]
return context, name, False, decl
if end_token == ";" and stmt.startswith("typedef"): if end_token == ";" and stmt.startswith("typedef"):
# TODO: handle typedef's more intelligently # TODO: handle typedef's more intelligently
...@@ -731,7 +737,7 @@ class CppHeaderParser(object): ...@@ -731,7 +737,7 @@ class CppHeaderParser(object):
# since we filtered off the other places where '(' can normally occur: # since we filtered off the other places where '(' can normally occur:
# - code blocks # - code blocks
# - function pointer typedef's # - function pointer typedef's
decl = self.parse_func_decl(stmt, use_umat=use_umat, docstring=docstring) decl = self.parse_func_decl(stmt, mat=mat, docstring=docstring)
# we return parse_flag == False to prevent the parser to look inside function/method bodies # we return parse_flag == False to prevent the parser to look inside function/method bodies
# (except for tracking the nested blocks) # (except for tracking the nested blocks)
return stmt_type, "", False, decl return stmt_type, "", False, decl
...@@ -827,7 +833,7 @@ class CppHeaderParser(object): ...@@ -827,7 +833,7 @@ class CppHeaderParser(object):
l = l[pos+2:] l = l[pos+2:]
state = SCAN state = SCAN
if l.startswith('CV__'): # just ignore this lines if l.startswith('CV__') or l.startswith('__CV_'): # just ignore these lines
#print('IGNORE: ' + l) #print('IGNORE: ' + l)
state = SCAN state = SCAN
continue continue
...@@ -841,11 +847,17 @@ class CppHeaderParser(object): ...@@ -841,11 +847,17 @@ class CppHeaderParser(object):
if not token: if not token:
block_head += " " + l block_head += " " + l
block_head = block_head.strip()
if len(block_head) > 0 and block_head[-1] == ')' and block_head.startswith('CV_ENUM_FLAGS('):
l = ''
token = ';'
else:
break break
if token == "//": if token == "//":
block_head += " " + l[:pos] block_head += " " + l[:pos]
break l = ''
continue
if token == "/*": if token == "/*":
block_head += " " + l[:pos] block_head += " " + l[:pos]
...@@ -896,20 +908,29 @@ class CppHeaderParser(object): ...@@ -896,20 +908,29 @@ class CppHeaderParser(object):
docstring = docstring.strip() docstring = docstring.strip()
stmt_type, name, parse_flag, decl = self.parse_stmt(stmt, token, docstring=docstring) stmt_type, name, parse_flag, decl = self.parse_stmt(stmt, token, docstring=docstring)
if decl: if decl:
if stmt_type == "enum": if stmt_type.startswith("enum"):
for d in decl: decls.append([stmt_type + " " + self.get_dotted_name(name), "", [], decl, None, ""])
decls.append(d)
else: else:
decls.append(decl) decls.append(decl)
if self._generate_gpumat_decls and "cv.cuda." in decl[0]:
# If function takes as one of arguments Mat or vector<Mat> - we want to create the
# same declaration working with GpuMat (this is important for T-Api access)
args = decl[3]
has_mat = len(list(filter(lambda x: x[0] in {"Mat", "vector_Mat"}, args))) > 0
if has_mat:
_, _, _, gpumat_decl = self.parse_stmt(stmt, token, mat="cuda::GpuMat", docstring=docstring)
decls.append(gpumat_decl)
if self._generate_umat_decls: if self._generate_umat_decls:
# If function takes as one of arguments Mat or vector<Mat> - we want to create the # If function takes as one of arguments Mat or vector<Mat> - we want to create the
# same declaration working with UMat (this is important for T-Api access) # same declaration working with UMat (this is important for T-Api access)
args = decl[3] args = decl[3]
has_mat = len(list(filter(lambda x: x[0] in {"Mat", "vector_Mat"}, args))) > 0 has_mat = len(list(filter(lambda x: x[0] in {"Mat", "vector_Mat"}, args))) > 0
if has_mat: if has_mat:
_, _, _, umat_decl = self.parse_stmt(stmt, token, use_umat=True, docstring=docstring) _, _, _, umat_decl = self.parse_stmt(stmt, token, mat="UMat", docstring=docstring)
decls.append(umat_decl) decls.append(umat_decl)
docstring = "" docstring = ""
if stmt_type == "namespace": if stmt_type == "namespace":
chunks = [block[1] for block in self.block_stack if block[0] == 'namespace'] + [name] chunks = [block[1] for block in self.block_stack if block[0] == 'namespace'] + [name]
...@@ -952,7 +973,7 @@ class CppHeaderParser(object): ...@@ -952,7 +973,7 @@ class CppHeaderParser(object):
print() print()
if __name__ == '__main__': if __name__ == '__main__':
parser = CppHeaderParser(generate_umat_decls=True) parser = CppHeaderParser(generate_umat_decls=True, generate_gpumat_decls=False)
decls = [] decls = []
for hname in opencv_hdr_list: for hname in opencv_hdr_list:
decls += parser.parse(hname) decls += parser.parse(hname)
......
#ifdef HAVE_OPENCV_STITCHING #ifdef HAVE_OPENCV_STITCHING
typedef Stitcher::Status Status; typedef Stitcher::Status Status;
template<>
PyObject* pyopencv_from(const Status& value)
{
return PyInt_FromLong(value);
}
#endif #endif
#ifdef HAVE_OPENCV_VIDEOIO #ifdef HAVE_OPENCV_VIDEOIO
typedef std::vector<VideoCaptureAPIs> vector_VideoCaptureAPIs; typedef std::vector<VideoCaptureAPIs> vector_VideoCaptureAPIs;
template<>
bool pyopencv_to(PyObject *o, cv::VideoCaptureAPIs &v, const char *name)
{
(void)name;
v = CAP_ANY;
if (!o || o == Py_None)
return false;
else if (PyLong_Check(o))
{
v = VideoCaptureAPIs((int64)PyLong_AsLongLong(o));
return true;
}
else if (PyInt_Check(o))
{
v = VideoCaptureAPIs((int64)PyInt_AS_LONG(o));
return true;
}
else
return false;
}
template<>
PyObject* pyopencv_from(const cv::VideoCaptureAPIs &v)
{
return pyopencv_from((int)(v));
}
template<> struct pyopencvVecConverter<cv::VideoCaptureAPIs> template<> struct pyopencvVecConverter<cv::VideoCaptureAPIs>
{ {
static bool to(PyObject* obj, std::vector<cv::VideoCaptureAPIs>& value, const ArgInfo info) static bool to(PyObject* obj, std::vector<cv::VideoCaptureAPIs>& value, const ArgInfo info)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册