Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
自由之枫~
opencv
提交
8f4473b3
O
opencv
项目概览
自由之枫~
/
opencv
与 Fork 源项目一致
Fork自
OpenCV / opencv
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
opencv
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8f4473b3
编写于
1月 20, 2022
作者:
A
Alexander Alekhin
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #21478 from VadimLevin:dev/vlevin/pysubmodules-initialization-fix
上级
25f25275
eca2d927
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
189 addition
and
41 deletion
+189
-41
modules/core/include/opencv2/core/bindings_utils.hpp
modules/core/include/opencv2/core/bindings_utils.hpp
+6
-0
modules/python/src2/cv2.cpp
modules/python/src2/cv2.cpp
+168
-41
modules/python/test/test_misc.py
modules/python/test/test_misc.py
+15
-0
未找到文件。
modules/core/include/opencv2/core/bindings_utils.hpp
浏览文件 @
8f4473b3
...
...
@@ -213,6 +213,12 @@ AsyncArray testAsyncException()
return
p
.
getArrayResult
();
}
namespace
nested
{
CV_WRAP
static
inline
bool
testEchoBooleanFunction
(
bool
flag
)
{
return
flag
;
}
}
// namespace nested
//! @} // core_utils
}
// namespace cv::utils
...
...
modules/python/src2/cv2.cpp
浏览文件 @
8f4473b3
...
...
@@ -2100,45 +2100,151 @@ struct ConstDef
long
long
val
;
};
static
void
init_submodule
(
PyObject
*
root
,
const
char
*
name
,
PyMethodDef
*
methods
,
ConstDef
*
consts
)
{
// traverse and create nested submodules
std
::
string
s
=
name
;
size_t
i
=
s
.
find
(
'.'
);
while
(
i
<
s
.
length
()
&&
i
!=
std
::
string
::
npos
)
{
size_t
j
=
s
.
find
(
'.'
,
i
);
if
(
j
==
std
::
string
::
npos
)
j
=
s
.
length
();
std
::
string
short_name
=
s
.
substr
(
i
,
j
-
i
);
std
::
string
full_name
=
s
.
substr
(
0
,
j
);
i
=
j
+
1
;
PyObject
*
d
=
PyModule_GetDict
(
root
);
PyObject
*
submod
=
PyDict_GetItemString
(
d
,
short_name
.
c_str
());
if
(
submod
==
NULL
)
{
submod
=
PyImport_AddModule
(
full_name
.
c_str
());
PyDict_SetItemString
(
d
,
short_name
.
c_str
(),
submod
);
}
if
(
short_name
!=
""
)
root
=
submod
;
}
// populate module's dict
PyObject
*
d
=
PyModule_GetDict
(
root
);
for
(
PyMethodDef
*
m
=
methods
;
m
->
ml_name
!=
NULL
;
++
m
)
{
PyObject
*
method_obj
=
PyCFunction_NewEx
(
m
,
NULL
,
NULL
);
PyDict_SetItemString
(
d
,
m
->
ml_name
,
method_obj
);
Py_DECREF
(
method_obj
);
}
for
(
ConstDef
*
c
=
consts
;
c
->
name
!=
NULL
;
++
c
)
{
PyDict_SetItemString
(
d
,
c
->
name
,
PyLong_FromLongLong
(
c
->
val
));
}
static
inline
bool
strStartsWith
(
const
std
::
string
&
str
,
const
std
::
string
&
prefix
)
{
return
prefix
.
empty
()
||
\
(
str
.
size
()
>=
prefix
.
size
()
&&
std
::
memcmp
(
str
.
data
(),
prefix
.
data
(),
prefix
.
size
())
==
0
);
}
static
inline
bool
strEndsWith
(
const
std
::
string
&
str
,
char
symbol
)
{
return
!
str
.
empty
()
&&
str
[
str
.
size
()
-
1
]
==
symbol
;
}
/**
* \brief Creates a submodule of the `root`. Missing parents submodules
* are created as needed. If name equals to parent module name than
* borrowed reference to parent module is returned (no reference counting
* are done).
* Submodule lifetime is managed by the parent module.
* If nested submodules are created than the lifetime is managed by the
* predecessor submodule in a list.
*
* \param parent_module Parent module object.
* \param name Submodule name.
* \return borrowed reference to the created submodule.
* If any of submodules can't be created than NULL is returned.
*/
static
PyObject
*
createSubmodule
(
PyObject
*
parent_module
,
const
std
::
string
&
name
)
{
if
(
!
parent_module
)
{
return
PyErr_Format
(
PyExc_ImportError
,
"Bindings generation error. "
"Parent module is NULL during the submodule '%s' creation"
,
name
.
c_str
()
);
}
if
(
strEndsWith
(
name
,
'.'
))
{
return
PyErr_Format
(
PyExc_ImportError
,
"Bindings generation error. "
"Submodule can't end with a dot. Got: %s"
,
name
.
c_str
()
);
}
const
std
::
string
parent_name
=
PyModule_GetName
(
parent_module
);
/// Special case handling when caller tries to register a submodule of the parent module with
/// the same name
if
(
name
==
parent_name
)
{
return
parent_module
;
}
if
(
!
strStartsWith
(
name
,
parent_name
))
{
return
PyErr_Format
(
PyExc_ImportError
,
"Bindings generation error. "
"Submodule name should always start with a parent module name. "
"Parent name: %s. Submodule name: %s"
,
parent_name
.
c_str
(),
name
.
c_str
()
);
}
size_t
submodule_name_end
=
name
.
find
(
'.'
,
parent_name
.
size
()
+
1
);
/// There is no intermediate submodules in the provided name
if
(
submodule_name_end
==
std
::
string
::
npos
)
{
submodule_name_end
=
name
.
size
();
}
PyObject
*
submodule
=
parent_module
;
for
(
size_t
submodule_name_start
=
parent_name
.
size
()
+
1
;
submodule_name_start
<
name
.
size
();
)
{
const
std
::
string
submodule_name
=
name
.
substr
(
submodule_name_start
,
submodule_name_end
-
submodule_name_start
);
const
std
::
string
full_submodule_name
=
name
.
substr
(
0
,
submodule_name_end
);
PyObject
*
parent_module_dict
=
PyModule_GetDict
(
submodule
);
/// If submodule already exists it can be found in the parent module dictionary,
/// otherwise it should be added to it.
submodule
=
PyDict_GetItemString
(
parent_module_dict
,
submodule_name
.
c_str
());
if
(
!
submodule
)
{
submodule
=
PyImport_AddModule
(
full_submodule_name
.
c_str
());
if
(
PyDict_SetItemString
(
parent_module_dict
,
submodule_name
.
c_str
(),
submodule
)
<
0
)
{
Py_CLEAR
(
submodule
);
return
PyErr_Format
(
PyExc_ImportError
,
"Can't register a submodule '%s' (full name: '%s')"
,
submodule_name
.
c_str
(),
full_submodule_name
.
c_str
()
);
}
/// PyDict_SetItemString doesn't steal a reference so the reference counter
/// of the submodule should be decremented to bind submodule lifetime to the
/// parent module
Py_DECREF
(
submodule
);
}
submodule_name_start
=
submodule_name_end
+
1
;
submodule_name_end
=
name
.
find
(
'.'
,
submodule_name_start
);
if
(
submodule_name_end
==
std
::
string
::
npos
)
{
submodule_name_end
=
name
.
size
();
}
}
return
submodule
;
}
static
bool
init_submodule
(
PyObject
*
root
,
const
char
*
name
,
PyMethodDef
*
methods
,
ConstDef
*
consts
)
{
// traverse and create nested submodules
PyObject
*
submodule
=
createSubmodule
(
root
,
name
);
if
(
!
submodule
)
{
return
false
;
}
// populate module's dict
PyObject
*
d
=
PyModule_GetDict
(
submodule
);
for
(
PyMethodDef
*
m
=
methods
;
m
->
ml_name
!=
NULL
;
++
m
)
{
PyObject
*
method_obj
=
PyCFunction_NewEx
(
m
,
NULL
,
NULL
);
if
(
PyDict_SetItemString
(
d
,
m
->
ml_name
,
method_obj
)
<
0
)
{
PyErr_Format
(
PyExc_ImportError
,
"Can't register function %s in module: %s"
,
m
->
ml_name
,
name
);
Py_CLEAR
(
method_obj
);
return
false
;
}
Py_DECREF
(
method_obj
);
}
for
(
ConstDef
*
c
=
consts
;
c
->
name
!=
NULL
;
++
c
)
{
PyObject
*
const_obj
=
PyLong_FromLongLong
(
c
->
val
);
if
(
PyDict_SetItemString
(
d
,
c
->
name
,
const_obj
)
<
0
)
{
PyErr_Format
(
PyExc_ImportError
,
"Can't register constant %s in module %s"
,
c
->
name
,
name
);
Py_CLEAR
(
const_obj
);
return
false
;
}
Py_DECREF
(
const_obj
);
}
return
true
;
}
#include "pyopencv_generated_modules_content.h"
...
...
@@ -2146,7 +2252,10 @@ static void init_submodule(PyObject * root, const char * name, PyMethodDef * met
static
bool
init_body
(
PyObject
*
m
)
{
#define CVPY_MODULE(NAMESTR, NAME) \
init_submodule(m, MODULESTR NAMESTR, methods_##NAME, consts_##NAME)
if (!init_submodule(m, MODULESTR NAMESTR, methods_##NAME, consts_##NAME)) \
{ \
return false; \
}
#include "pyopencv_generated_modules.h"
#undef CVPY_MODULE
...
...
@@ -2163,7 +2272,13 @@ static bool init_body(PyObject * m)
PyObject
*
d
=
PyModule_GetDict
(
m
);
PyDict_SetItemString
(
d
,
"__version__"
,
PyString_FromString
(
CV_VERSION
));
PyObject
*
version_obj
=
PyString_FromString
(
CV_VERSION
);
if
(
PyDict_SetItemString
(
d
,
"__version__"
,
version_obj
)
<
0
)
{
PyErr_SetString
(
PyExc_ImportError
,
"Can't update module version"
);
Py_CLEAR
(
version_obj
);
return
false
;
}
Py_DECREF
(
version_obj
);
PyObject
*
opencv_error_dict
=
PyDict_New
();
PyDict_SetItemString
(
opencv_error_dict
,
"file"
,
Py_None
);
...
...
@@ -2177,7 +2292,18 @@ static bool init_body(PyObject * m)
PyDict_SetItemString
(
d
,
"error"
,
opencv_error
);
#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I))
#define PUBLISH_(I, var_name, type_obj) \
PyObject* type_obj = PyInt_FromLong(I); \
if (PyDict_SetItemString(d, var_name, type_obj) < 0) \
{ \
PyErr_SetString(PyExc_ImportError, "Can't register " var_name " constant"); \
Py_CLEAR(type_obj); \
return false; \
} \
Py_DECREF(type_obj);
#define PUBLISH(I) PUBLISH_(I, #I, I ## _obj)
PUBLISH
(
CV_8U
);
PUBLISH
(
CV_8UC1
);
PUBLISH
(
CV_8UC2
);
...
...
@@ -2213,6 +2339,7 @@ static bool init_body(PyObject * m)
PUBLISH
(
CV_64FC2
);
PUBLISH
(
CV_64FC3
);
PUBLISH
(
CV_64FC4
);
#undef PUBLISH_
#undef PUBLISH
return
true
;
...
...
modules/python/test/test_misc.py
浏览文件 @
8f4473b3
#!/usr/bin/env python
from
__future__
import
print_function
import
sys
import
ctypes
from
functools
import
partial
from
collections
import
namedtuple
...
...
@@ -596,6 +597,20 @@ class Arguments(NewOpenCVTests):
self
.
assertTrue
(
isinstance
(
rr
,
tuple
),
msg
=
type
(
rrv
))
self
.
assertEqual
(
len
(
rr
),
3
)
def
test_nested_function_availability
(
self
):
self
.
assertTrue
(
hasattr
(
cv
.
utils
,
"nested"
),
msg
=
"Module is not generated for nested namespace"
)
self
.
assertTrue
(
hasattr
(
cv
.
utils
.
nested
,
"testEchoBooleanFunction"
),
msg
=
"Function in nested module is not available"
)
self
.
assertEqual
(
sys
.
getrefcount
(
cv
.
utils
.
nested
),
2
,
msg
=
"Nested submodule lifetime should be managed by "
"the parent module so the reference count should be "
"2, because `getrefcount` temporary increases it."
)
for
flag
in
(
True
,
False
):
self
.
assertEqual
(
flag
,
cv
.
utils
.
nested
.
testEchoBooleanFunction
(
flag
),
msg
=
"Function in nested module returns wrong result"
)
class
SamplesFindFile
(
NewOpenCVTests
):
def
test_ExistedFile
(
self
):
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录