25
25
return failmsgp("Incorrect type of self (must be '${name}' or its derivative)");
26
26
""" )
27
27
28
- gen_template_call_constructor_prelude = Template ("""self = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
29
- new (&(self->v)) Ptr<$cname>(); // init Ptr with placement new
28
+ gen_template_call_constructor_prelude = Template ("""new (&(self->v)) Ptr<$cname>(); // init Ptr with placement new
30
29
if(self) """ )
31
30
32
31
gen_template_call_constructor = Template ("""self->v.reset(new ${cname}${args})""" )
33
32
34
- gen_template_simple_call_constructor_prelude = Template ("""self = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
35
- if(self) """ )
33
+ gen_template_simple_call_constructor_prelude = Template ("""if(self) """ )
36
34
37
35
gen_template_simple_call_constructor = Template ("""new (&(self->v)) ${cname}${args}""" )
38
36
189
187
pyopencv_${name}_Type.tp_dealloc = pyopencv_${name}_dealloc;
190
188
pyopencv_${name}_Type.tp_repr = pyopencv_${name}_repr;
191
189
pyopencv_${name}_Type.tp_getset = pyopencv_${name}_getseters;
190
+ pyopencv_${name}_Type.tp_init = (initproc)${constructor};
192
191
pyopencv_${name}_Type.tp_methods = pyopencv_${name}_methods;${extra_specials}
193
192
}
194
193
""" )
@@ -280,6 +279,7 @@ def __init__(self, name, decl=None):
280
279
self .props = []
281
280
self .consts = {}
282
281
self .base = None
282
+ self .constructor = None
283
283
customname = False
284
284
285
285
if decl :
@@ -353,6 +353,9 @@ def gen_code(self, all_classes):
353
353
sorted_methods = list (self .methods .items ())
354
354
sorted_methods .sort ()
355
355
356
+ if self .constructor is not None :
357
+ methods_code .write (self .constructor .gen_code (all_classes ))
358
+
356
359
for mname , m in sorted_methods :
357
360
methods_code .write (m .gen_code (all_classes ))
358
361
methods_inits .write (m .get_tab_entry ())
@@ -361,10 +364,14 @@ def gen_code(self, all_classes):
361
364
if self .base and self .base in all_classes :
362
365
baseptr = "&pyopencv_" + all_classes [self .base ].name + "_Type"
363
366
367
+ constructor_name = "0"
368
+ if self .constructor is not None :
369
+ constructor_name = self .constructor .get_wrapper_name ()
370
+
364
371
code = gen_template_type_impl .substitute (name = self .name , wname = self .wname , cname = self .cname ,
365
372
getset_code = getset_code .getvalue (), getset_inits = getset_inits .getvalue (),
366
373
methods_code = methods_code .getvalue (), methods_inits = methods_inits .getvalue (),
367
- baseptr = baseptr , extra_specials = "" )
374
+ baseptr = baseptr , constructor = constructor_name , extra_specials = "" )
368
375
369
376
return code
370
377
@@ -521,12 +528,13 @@ def init_pyproto(self):
521
528
522
529
523
530
class FuncInfo (object ):
524
- def __init__ (self , classname , name , cname , isconstructor , namespace ):
531
+ def __init__ (self , classname , name , cname , isconstructor , namespace , isclassmethod ):
525
532
self .classname = classname
526
533
self .name = name
527
534
self .cname = cname
528
535
self .isconstructor = isconstructor
529
536
self .namespace = namespace
537
+ self .isclassmethod = isclassmethod
530
538
self .variants = []
531
539
532
540
def add_variant (self , decl ):
@@ -540,11 +548,19 @@ def get_wrapper_name(self):
540
548
name = "getelem"
541
549
else :
542
550
classname = ""
551
+
552
+ if self .isclassmethod :
553
+ name += "_cls"
554
+
543
555
return "pyopencv_" + self .namespace .replace ('.' ,'_' ) + '_' + classname + name
544
556
545
- def get_wrapper_prototype (self ):
557
+ def get_wrapper_prototype (self , all_classes ):
546
558
full_fname = self .get_wrapper_name ()
547
- if self .classname and not self .isconstructor :
559
+ if self .isconstructor :
560
+ return "static int {fn_name}(pyopencv_{type_name}_t* self, PyObject* args, PyObject* kw)" .format (
561
+ fn_name = full_fname , type_name = all_classes [self .classname ].name )
562
+
563
+ if self .classname :
548
564
self_arg = "self"
549
565
else :
550
566
self_arg = ""
@@ -591,12 +607,16 @@ def get_tab_entry(self):
591
607
# Convert unicode chars to xml representation, but keep as string instead of bytes
592
608
full_docstring = full_docstring .encode ('ascii' , errors = 'xmlcharrefreplace' ).decode ()
593
609
594
- return Template (' {"$py_funcname", (PyCFunction)$wrap_funcname, METH_VARARGS | METH_KEYWORDS, "$py_docstring"},\n '
610
+ flags = ["METH_VARARGS" , "METH_KEYWORDS" ]
611
+ if self .isclassmethod :
612
+ flags .append ("METH_CLASS" )
613
+
614
+ return Template (' {"$py_funcname", (PyCFunction)$wrap_funcname, $flags, "$py_docstring"},\n '
595
615
).substitute (py_funcname = self .variants [0 ].wname , wrap_funcname = self .get_wrapper_name (),
596
- py_docstring = full_docstring )
616
+ flags = " | " . join ( flags ), py_docstring = full_docstring )
597
617
598
618
def gen_code (self , all_classes ):
599
- proto = self .get_wrapper_prototype ()
619
+ proto = self .get_wrapper_prototype (all_classes )
600
620
code = "%s\n {\n " % (proto ,)
601
621
code += " using namespace %s;\n \n " % self .namespace .replace ('.' , '::' )
602
622
@@ -609,7 +629,9 @@ def gen_code(self, all_classes):
609
629
selfinfo = all_classes [self .classname ]
610
630
if not self .isconstructor :
611
631
amp = "&" if selfinfo .issimple else ""
612
- if selfinfo .isalgorithm :
632
+ if self .isclassmethod :
633
+ pass
634
+ elif selfinfo .isalgorithm :
613
635
code += gen_template_check_self_algo .substitute (name = selfinfo .name , cname = selfinfo .cname , amp = amp )
614
636
else :
615
637
get = "" if selfinfo .issimple else ".get()"
@@ -692,7 +714,6 @@ def gen_code(self, all_classes):
692
714
code_args += ")"
693
715
694
716
if self .isconstructor :
695
- code_decl += " pyopencv_%s_t* self = 0;\n " % selfinfo .name
696
717
if selfinfo .issimple :
697
718
templ_prelude = gen_template_simple_call_constructor_prelude
698
719
templ = gen_template_simple_call_constructor
@@ -708,7 +729,7 @@ def gen_code(self, all_classes):
708
729
if v .rettype :
709
730
code_decl += " " + v .rettype + " retval;\n "
710
731
code_fcall += "retval = "
711
- if ismethod :
732
+ if ismethod and not self . isclassmethod :
712
733
code_fcall += "_self_->" + self .cname
713
734
else :
714
735
code_fcall += self .cname
@@ -750,7 +771,7 @@ def gen_code(self, all_classes):
750
771
code_ret = "Py_RETURN_NONE"
751
772
elif len (v .py_outlist ) == 1 :
752
773
if self .isconstructor :
753
- code_ret = "return (PyObject*)self "
774
+ code_ret = "return 0 "
754
775
else :
755
776
aname , argno = v .py_outlist [0 ]
756
777
code_ret = "return pyopencv_from(%s)" % (aname ,)
@@ -773,7 +794,11 @@ def gen_code(self, all_classes):
773
794
else :
774
795
# try to execute each signature
775
796
code += " PyErr_Clear();\n \n " .join ([" {\n " + v + " }\n " for v in all_code_variants ])
776
- code += "\n return NULL;\n }\n \n "
797
+
798
+ def_ret = "NULL"
799
+ if self .isconstructor :
800
+ def_ret = "-1"
801
+ code += "\n return %s;\n }\n \n " % def_ret
777
802
return code
778
803
779
804
@@ -796,6 +821,7 @@ def clear(self):
796
821
self .code_funcs = StringIO ()
797
822
self .code_type_reg = StringIO ()
798
823
self .code_ns_reg = StringIO ()
824
+ self .code_type_publish = StringIO ()
799
825
self .class_idx = 0
800
826
801
827
def add_class (self , stype , name , decl ):
@@ -848,20 +874,32 @@ def add_func(self, decl):
848
874
isclassmethod = True
849
875
elif m .startswith ("=" ):
850
876
name = m [1 :]
851
- if isclassmethod :
852
- name = "_" .join (classes + [name ])
853
- classname = ''
854
- elif isconstructor :
877
+ if isconstructor :
855
878
name = "_" .join (classes [:- 1 ]+ [name ])
856
879
857
- if classname and not isconstructor :
858
- cname = barename
880
+ if isclassmethod :
881
+ # Add it as a method to the class
859
882
func_map = self .classes [classname ].methods
860
- else :
883
+ func = func_map .setdefault (name , FuncInfo (classname , name , cname , isconstructor , namespace , isclassmethod ))
884
+ func .add_variant (decl )
885
+
886
+ # Add it as global function
887
+ g_name = "_" .join (classes + [name ])
861
888
func_map = self .namespaces .setdefault (namespace , Namespace ()).funcs
889
+ func = func_map .setdefault (g_name , FuncInfo ("" , g_name , cname , isconstructor , namespace , False ))
890
+ func .add_variant (decl )
891
+ else :
892
+ if classname and not isconstructor :
893
+ cname = barename
894
+ func_map = self .classes [classname ].methods
895
+ else :
896
+ func_map = self .namespaces .setdefault (namespace , Namespace ()).funcs
897
+
898
+ func = func_map .setdefault (name , FuncInfo (classname , name , cname , isconstructor , namespace , isclassmethod ))
899
+ func .add_variant (decl )
862
900
863
- func = func_map . setdefault ( name , FuncInfo ( classname , name , cname , isconstructor , namespace ))
864
- func . add_variant ( decl )
901
+ if classname and isconstructor :
902
+ self . classes [ classname ]. constructor = func
865
903
866
904
867
905
def gen_namespace (self , ns_name ):
@@ -870,6 +908,8 @@ def gen_namespace(self, ns_name):
870
908
871
909
self .code_ns_reg .write ('static PyMethodDef methods_%s[] = {\n ' % wname )
872
910
for name , func in sorted (ns .funcs .items ()):
911
+ if func .isconstructor :
912
+ continue
873
913
self .code_ns_reg .write (func .get_tab_entry ())
874
914
self .code_ns_reg .write (' {NULL, NULL}\n };\n \n ' )
875
915
@@ -960,12 +1000,15 @@ def gen(self, srcfiles, output_path):
960
1000
self .code_types .write (code )
961
1001
if not classinfo .ismap :
962
1002
self .code_type_reg .write ("MKTYPE2(%s);\n " % (classinfo .name ,) )
1003
+ self .code_type_publish .write ("PUBLISH_OBJECT(\" {name}\" , pyopencv_{name}_Type);\n " .format (name = classinfo .name ))
963
1004
964
1005
# step 3: generate the code for all the global functions
965
1006
for ns_name , ns in sorted (self .namespaces .items ()):
966
1007
if ns_name .split ('.' )[0 ] != 'cv' :
967
1008
continue
968
1009
for name , func in sorted (ns .funcs .items ()):
1010
+ if func .isconstructor :
1011
+ continue
969
1012
code = func .gen_code (self .classes )
970
1013
self .code_funcs .write (code )
971
1014
self .gen_namespace (ns_name )
@@ -983,6 +1026,7 @@ def gen(self, srcfiles, output_path):
983
1026
self .save (output_path , "pyopencv_generated_types.h" , self .code_types )
984
1027
self .save (output_path , "pyopencv_generated_type_reg.h" , self .code_type_reg )
985
1028
self .save (output_path , "pyopencv_generated_ns_reg.h" , self .code_ns_reg )
1029
+ self .save (output_path , "pyopencv_generated_type_publish.h" , self .code_type_publish )
986
1030
987
1031
if __name__ == "__main__" :
988
1032
srcfiles = hdr_parser .opencv_hdr_list
0 commit comments