@@ -2100,53 +2100,162 @@ struct ConstDef
2100
2100
long long val;
2101
2101
};
2102
2102
2103
- static void init_submodule (PyObject * root, const char * name, PyMethodDef * methods, ConstDef * consts)
2104
- {
2105
- // traverse and create nested submodules
2106
- std::string s = name;
2107
- size_t i = s.find (' .' );
2108
- while (i < s.length () && i != std::string::npos)
2109
- {
2110
- size_t j = s.find (' .' , i);
2111
- if (j == std::string::npos)
2112
- j = s.length ();
2113
- std::string short_name = s.substr (i, j-i);
2114
- std::string full_name = s.substr (0 , j);
2115
- i = j+1 ;
2116
-
2117
- PyObject * d = PyModule_GetDict (root);
2118
- PyObject * submod = PyDict_GetItemString (d, short_name.c_str ());
2119
- if (submod == NULL )
2120
- {
2121
- submod = PyImport_AddModule (full_name.c_str ());
2122
- PyDict_SetItemString (d, short_name.c_str (), submod);
2123
- }
2124
-
2125
- if (short_name != " " )
2126
- root = submod;
2127
- }
2128
-
2129
- // populate module's dict
2130
- PyObject * d = PyModule_GetDict (root);
2131
- for (PyMethodDef * m = methods; m->ml_name != NULL ; ++m)
2132
- {
2133
- PyObject * method_obj = PyCFunction_NewEx (m, NULL , NULL );
2134
- PyDict_SetItemString (d, m->ml_name , method_obj);
2135
- Py_DECREF (method_obj);
2136
- }
2137
- for (ConstDef * c = consts; c->name != NULL ; ++c)
2138
- {
2139
- PyDict_SetItemString (d, c->name , PyLong_FromLongLong (c->val ));
2140
- }
2103
+ static inline bool strStartsWith (const std::string& str, const std::string& prefix) {
2104
+ return prefix.empty () || \
2105
+ (str.size () >= prefix.size () && std::memcmp (str.data (), prefix.data (), prefix.size ()) == 0 );
2106
+ }
2107
+
2108
+ static inline bool strEndsWith (const std::string& str, char symbol) {
2109
+ return !str.empty () && str[str.size () - 1 ] == symbol;
2110
+ }
2111
+
2112
+ /* *
2113
+ * \brief Creates a submodule of the `root`. Missing parents submodules
2114
+ * are created as needed. If name equals to parent module name than
2115
+ * borrowed reference to parent module is returned (no reference counting
2116
+ * are done).
2117
+ * Submodule lifetime is managed by the parent module.
2118
+ * If nested submodules are created than the lifetime is managed by the
2119
+ * predecessor submodule in a list.
2120
+ *
2121
+ * \param parent_module Parent module object.
2122
+ * \param name Submodule name.
2123
+ * \return borrowed reference to the created submodule.
2124
+ * If any of submodules can't be created than NULL is returned.
2125
+ */
2126
+ static PyObject* createSubmodule (PyObject* parent_module, const std::string& name)
2127
+ {
2128
+ if (!parent_module)
2129
+ {
2130
+ return PyErr_Format (PyExc_ImportError,
2131
+ " Bindings generation error. "
2132
+ " Parent module is NULL during the submodule '%s' creation" ,
2133
+ name.c_str ()
2134
+ );
2135
+ }
2136
+ if (strEndsWith (name, ' .' ))
2137
+ {
2138
+ return PyErr_Format (PyExc_ImportError,
2139
+ " Bindings generation error. "
2140
+ " Submodule can't end with a dot. Got: %s" , name.c_str ()
2141
+ );
2142
+ }
2143
+
2144
+ const std::string parent_name = PyModule_GetName (parent_module);
2145
+
2146
+ // / Special case handling when caller tries to register a submodule of the parent module with
2147
+ // / the same name
2148
+ if (name == parent_name) {
2149
+ return parent_module;
2150
+ }
2151
+
2152
+ if (!strStartsWith (name, parent_name))
2153
+ {
2154
+ return PyErr_Format (PyExc_ImportError,
2155
+ " Bindings generation error. "
2156
+ " Submodule name should always start with a parent module name. "
2157
+ " Parent name: %s. Submodule name: %s" , parent_name.c_str (),
2158
+ name.c_str ()
2159
+ );
2160
+ }
2161
+
2162
+ size_t submodule_name_end = name.find (' .' , parent_name.size () + 1 );
2163
+ // / There is no intermediate submodules in the provided name
2164
+ if (submodule_name_end == std::string::npos)
2165
+ {
2166
+ submodule_name_end = name.size ();
2167
+ }
2168
+
2169
+ PyObject* submodule = parent_module;
2170
+
2171
+ for (size_t submodule_name_start = parent_name.size () + 1 ;
2172
+ submodule_name_start < name.size (); )
2173
+ {
2174
+ const std::string submodule_name = name.substr (submodule_name_start,
2175
+ submodule_name_end - submodule_name_start);
2176
+
2177
+ const std::string full_submodule_name = name.substr (0 , submodule_name_end);
2178
+
2179
+
2180
+ PyObject* parent_module_dict = PyModule_GetDict (submodule);
2181
+ // / If submodule already exists it can be found in the parent module dictionary,
2182
+ // / otherwise it should be added to it.
2183
+ submodule = PyDict_GetItemString (parent_module_dict,
2184
+ submodule_name.c_str ());
2185
+ if (!submodule)
2186
+ {
2187
+ submodule = PyImport_AddModule (full_submodule_name.c_str ());
2188
+ if (PyDict_SetItemString (parent_module_dict, submodule_name.c_str (), submodule) < 0 ) {
2189
+ Py_CLEAR (submodule);
2190
+ return PyErr_Format (PyExc_ImportError,
2191
+ " Can't register a submodule '%s' (full name: '%s')" ,
2192
+ submodule_name.c_str (), full_submodule_name.c_str ()
2193
+ );
2194
+ }
2195
+ // / PyDict_SetItemString doesn't steal a reference so the reference counter
2196
+ // / of the submodule should be decremented to bind submodule lifetime to the
2197
+ // / parent module
2198
+ Py_DECREF (submodule);
2199
+ }
2141
2200
2201
+ submodule_name_start = submodule_name_end + 1 ;
2202
+
2203
+ submodule_name_end = name.find (' .' , submodule_name_start);
2204
+ if (submodule_name_end == std::string::npos) {
2205
+ submodule_name_end = name.size ();
2206
+ }
2207
+ }
2208
+ return submodule;
2209
+ }
2210
+
2211
+ static bool init_submodule (PyObject * root, const char * name, PyMethodDef * methods, ConstDef * consts)
2212
+ {
2213
+ // traverse and create nested submodules
2214
+ PyObject* submodule = createSubmodule (root, name);
2215
+ if (!submodule)
2216
+ {
2217
+ return false ;
2218
+ }
2219
+ // populate module's dict
2220
+ PyObject * d = PyModule_GetDict (submodule);
2221
+ for (PyMethodDef * m = methods; m->ml_name != NULL ; ++m)
2222
+ {
2223
+ PyObject * method_obj = PyCFunction_NewEx (m, NULL , NULL );
2224
+ if (PyDict_SetItemString (d, m->ml_name , method_obj) < 0 )
2225
+ {
2226
+ PyErr_Format (PyExc_ImportError,
2227
+ " Can't register function %s in module: %s" , m->ml_name , name
2228
+ );
2229
+ Py_CLEAR (method_obj);
2230
+ return false ;
2231
+ }
2232
+ Py_DECREF (method_obj);
2233
+ }
2234
+ for (ConstDef * c = consts; c->name != NULL ; ++c)
2235
+ {
2236
+ PyObject* const_obj = PyLong_FromLongLong (c->val );
2237
+ if (PyDict_SetItemString (d, c->name , const_obj) < 0 )
2238
+ {
2239
+ PyErr_Format (PyExc_ImportError,
2240
+ " Can't register constant %s in module %s" , c->name , name
2241
+ );
2242
+ Py_CLEAR (const_obj);
2243
+ return false ;
2244
+ }
2245
+ Py_DECREF (const_obj);
2246
+ }
2247
+ return true ;
2142
2248
}
2143
2249
2144
2250
#include " pyopencv_generated_modules_content.h"
2145
2251
2146
2252
static bool init_body (PyObject * m)
2147
2253
{
2148
2254
#define CVPY_MODULE (NAMESTR, NAME ) \
2149
- init_submodule (m, MODULESTR NAMESTR, methods_##NAME, consts_##NAME)
2255
+ if (!init_submodule (m, MODULESTR NAMESTR, methods_##NAME, consts_##NAME)) \
2256
+ { \
2257
+ return false ; \
2258
+ }
2150
2259
#include " pyopencv_generated_modules.h"
2151
2260
#undef CVPY_MODULE
2152
2261
@@ -2163,7 +2272,13 @@ static bool init_body(PyObject * m)
2163
2272
PyObject* d = PyModule_GetDict (m);
2164
2273
2165
2274
2166
- PyDict_SetItemString (d, " __version__" , PyString_FromString (CV_VERSION));
2275
+ PyObject* version_obj = PyString_FromString (CV_VERSION);
2276
+ if (PyDict_SetItemString (d, " __version__" , version_obj) < 0 ) {
2277
+ PyErr_SetString (PyExc_ImportError, " Can't update module version" );
2278
+ Py_CLEAR (version_obj);
2279
+ return false ;
2280
+ }
2281
+ Py_DECREF (version_obj);
2167
2282
2168
2283
PyObject *opencv_error_dict = PyDict_New ();
2169
2284
PyDict_SetItemString (opencv_error_dict, " file" , Py_None);
@@ -2177,7 +2292,18 @@ static bool init_body(PyObject * m)
2177
2292
PyDict_SetItemString (d, " error" , opencv_error);
2178
2293
2179
2294
2180
- #define PUBLISH (I ) PyDict_SetItemString(d, #I, PyInt_FromLong(I))
2295
+ #define PUBLISH_ (I, var_name, type_obj ) \
2296
+ PyObject* type_obj = PyInt_FromLong (I); \
2297
+ if (PyDict_SetItemString (d, var_name, type_obj) < 0 ) \
2298
+ { \
2299
+ PyErr_SetString (PyExc_ImportError, " Can't register " var_name " constant" ); \
2300
+ Py_CLEAR (type_obj); \
2301
+ return false ; \
2302
+ } \
2303
+ Py_DECREF (type_obj);
2304
+
2305
+ #define PUBLISH (I ) PUBLISH_(I, #I, I ## _obj)
2306
+
2181
2307
PUBLISH (CV_8U);
2182
2308
PUBLISH (CV_8UC1);
2183
2309
PUBLISH (CV_8UC2);
@@ -2213,6 +2339,7 @@ static bool init_body(PyObject * m)
2213
2339
PUBLISH (CV_64FC2);
2214
2340
PUBLISH (CV_64FC3);
2215
2341
PUBLISH (CV_64FC4);
2342
+ #undef PUBLISH_
2216
2343
#undef PUBLISH
2217
2344
2218
2345
return true ;
0 commit comments