~gjc/pybindgen/new-waf

« back to all changes in this revision

Viewing changes to pybindgen/cppclass_typehandlers.py

  • Committer: Gustavo J. A. M. Carneiro
  • Date: 2008-11-17 17:38:14 UTC
  • mfrom: (525.1.78 trunk)
  • Revision ID: gjc@gnome.org-20081117173814-6k0ejk3ovblbhla8
merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import warnings
2
2
 
3
3
from typehandlers.base import ForwardWrapperBase, ReverseWrapperBase, \
4
 
    Parameter, ReturnValue, TypeConfigurationError
 
4
    Parameter, ReturnValue, TypeConfigurationError, NotSupportedError
5
5
 
6
6
import cppclass
7
7
 
39
39
    CTYPES = []
40
40
    cpp_class = cppclass.CppClass('dummy') # CppClass instance
41
41
 
42
 
    def __init__(self, ctype):
43
 
        super(CppClassReturnValueBase, self).__init__(ctype)
 
42
    def __init__(self, ctype, is_const=False):
 
43
        super(CppClassReturnValueBase, self).__init__(ctype, is_const=is_const)
44
44
        ## name of the PyFoo * variable used in return value building
45
45
        self.py_name = None
46
46
 
145
145
        self.cpp_class.write_create_instance(wrapper.before_call,
146
146
                                             "%s->obj" % self.py_name,
147
147
                                             self.value)
 
148
        self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, self.py_name,
 
149
                                                                   "%s->obj" % self.py_name)
148
150
 
149
151
        wrapper.build_params.add_parameter("N", [self.py_name])
150
152
 
181
183
                    '*((%s *) %s)->obj' % (self.cpp_class.pystruct, self.py_name))
182
184
            else:
183
185
                implicit_conversion_sources = self.cpp_class.get_all_implicit_conversions()
184
 
                if not (implicit_conversion_sources and self.is_const):
 
186
                if not (implicit_conversion_sources and self.type_traits.target_is_const):
185
187
                    if self.default_value is not None:
186
188
                        self.py_name = wrapper.declarations.declare_variable(
187
189
                            self.cpp_class.pystruct+'*', self.name, 'NULL')
260
262
            self.cpp_class.write_create_instance(wrapper.before_call,
261
263
                                                 "%s->obj" % self.py_name,
262
264
                                                 '')
 
265
            self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, self.py_name,
 
266
                                                                       "%s->obj" % self.py_name)
263
267
            wrapper.call_params.append('*%s->obj' % (self.py_name,))
264
268
            wrapper.build_params.add_parameter("N", [self.py_name])
265
269
 
301
305
            self.cpp_class.write_create_instance(wrapper.before_call,
302
306
                                                 "%s->obj" % self.py_name,
303
307
                                                 self.value)
 
308
            self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, self.py_name,
 
309
                                                                       "%s->obj" % self.py_name)
304
310
            wrapper.build_params.add_parameter("N", [self.py_name])
305
311
        else:
306
312
            ## out/inout case:
308
314
            ## the ->obj pointer after the python call; this is so
309
315
            ## that the python code directly manipulates the object
310
316
            ## received as parameter, instead of a copy.
311
 
            if self.is_const:
 
317
            if self.type_traits.target_is_const:
312
318
                value = "(%s*) (&(%s))" % (self.cpp_class.full_name, self.value)
313
319
            else:
314
320
                value = "&(%s)" % self.value
330
336
            self.cpp_class.write_create_instance(wrapper.after_call,
331
337
                                                 "%s->obj" % self.py_name,
332
338
                                                 self.value)
 
339
            self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.after_call, self.py_name,
 
340
                                                                       "%s->obj" % self.py_name)
333
341
            wrapper.after_call.unindent()
334
342
            wrapper.after_call.write_code('}')
335
343
 
344
352
        """override to fix the ctype parameter with namespace information"""
345
353
        if ctype == self.cpp_class.name:
346
354
            ctype = self.cpp_class.full_name
347
 
        super(CppClassReturnValue, self).__init__(ctype)
348
 
        self.is_const = is_const
 
355
        super(CppClassReturnValue, self).__init__(ctype, is_const=is_const)
349
356
 
350
357
    def get_c_error_return(self): # only used in reverse wrappers
351
358
        """See ReturnValue.get_c_error_return"""
370
377
        self.cpp_class.write_create_instance(wrapper.after_call,
371
378
                                             "%s->obj" % py_name,
372
379
                                             self.value)
373
 
 
 
380
        self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.after_call, py_name,
 
381
                                                                   "%s->obj" % py_name)
374
382
        wrapper.build_params.add_parameter("N", [py_name], prepend=True)
375
383
 
376
384
    def convert_python_to_c(self, wrapper):
433
441
 
434
442
        if custodian is None:
435
443
            if transfer_ownership is None:
436
 
                raise TypeConfigurationError("transfer_ownership parameter missing")
 
444
                if self.type_traits.target_is_const:
 
445
                    transfer_ownership = False
 
446
                else:
 
447
                    raise TypeConfigurationError("transfer_ownership parameter missing")
437
448
            self.transfer_ownership = transfer_ownership
438
449
        else:
439
450
            if transfer_ownership is not None:
548
559
            ## Assign the C++ value to the Python wrapper
549
560
            if self.transfer_ownership:
550
561
                wrapper.before_call.write_code("%s->obj = %s;" % (py_name, value))
551
 
                wrapper.build_params.add_parameter("N", [py_name])
552
562
            else:
553
563
                if not isinstance(self.cpp_class.memory_policy, cppclass.ReferenceCountingPolicy):
554
564
                    ## The PyObject gets a temporary pointer to the
560
570
                        self.cpp_class.write_create_instance(wrapper.before_call,
561
571
                                                             "%s->obj" % self.py_name,
562
572
                                                             '*'+self.value)
563
 
                        wrapper.build_params.add_parameter("N", [self.py_name])
564
573
                    else:
565
574
                        ## out/inout case:
566
575
                        ## the callee receives a "temporary wrapper", which loses
567
576
                        ## the ->obj pointer after the python call; this is so
568
577
                        ## that the python code directly manipulates the object
569
578
                        ## received as parameter, instead of a copy.
570
 
                        if self.is_const:
 
579
                        if self.type_traits.target_is_const:
571
580
                            unconst_value = "(%s*) (%s)" % (self.cpp_class.full_name, value)
572
581
                        else:
573
582
                            unconst_value = value
594
603
                else:
595
604
                    ## The PyObject gets a new reference to the same obj
596
605
                    self.cpp_class.memory_policy.write_incref(wrapper.before_call, value)
597
 
                    if self.is_const:
 
606
                    if self.type_traits.target_is_const:
598
607
                        wrapper.before_call.write_code("%s->obj = (%s*) (%s);" %
599
608
                                                       (py_name, self.cpp_class.full_name, value))
600
609
                    else:
601
610
                        wrapper.before_call.write_code("%s->obj = %s;" % (py_name, value))
602
 
                    wrapper.build_params.add_parameter("N", [py_name])
603
611
        ## closes def write_create_new_wrapper():
604
612
 
605
613
        if self.cpp_class.helper_class is None:
606
 
            write_create_new_wrapper()
 
614
            try:
 
615
                self.cpp_class.wrapper_registry.write_lookup_wrapper(
 
616
                    wrapper.before_call, self.cpp_class.pystruct, py_name, value)
 
617
            except NotSupportedError:
 
618
                write_create_new_wrapper()
 
619
                self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, py_name,
 
620
                                                                           "%s->obj" % py_name)
 
621
            else:
 
622
                wrapper.before_call.write_code("if (%s == NULL)\n{" % py_name)
 
623
                wrapper.before_call.indent()
 
624
                write_create_new_wrapper()
 
625
                self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, py_name,
 
626
                                                                           "%s->obj" % py_name)
 
627
                wrapper.before_call.unindent()
 
628
                wrapper.before_call.write_code('}')
 
629
            wrapper.build_params.add_parameter("N", [py_name])
607
630
        else:
608
631
            wrapper.before_call.write_code("if (typeid(*(%s)) == typeid(%s))\n{"
609
632
                                          % (value, self.cpp_class.helper_class.name))
610
633
            wrapper.before_call.indent()
611
634
 
612
 
            if self.is_const:
 
635
            if self.type_traits.target_is_const:
613
636
                wrapper.before_call.write_code(
614
637
                    "%s = (%s*) (((%s*) ((%s*) %s))->m_pyself);"
615
638
                    % (py_name, self.cpp_class.pystruct,
626
649
            wrapper.before_call.unindent()
627
650
            wrapper.before_call.write_code("} else {")
628
651
            wrapper.before_call.indent()
629
 
            write_create_new_wrapper()
 
652
 
 
653
            try:
 
654
                self.cpp_class.wrapper_registry.write_lookup_wrapper(
 
655
                    wrapper.before_call, self.cpp_class.pystruct, py_name, value)
 
656
            except NotSupportedError:
 
657
                write_create_new_wrapper()
 
658
                self.cpp_class.wrapper_registry.write_register_new_wrapper(
 
659
                    wrapper.before_call, py_name, "%s->obj" % py_name)
 
660
            else:
 
661
                wrapper.before_call.write_code("if (%s == NULL)\n{" % py_name)
 
662
                wrapper.before_call.indent()
 
663
                write_create_new_wrapper()
 
664
                self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, py_name,
 
665
                                                                           "%s->obj" % py_name)
 
666
                wrapper.before_call.unindent()
 
667
                wrapper.before_call.write_code('}') # closes if (%s == NULL)
 
668
 
630
669
            wrapper.before_call.unindent()
631
 
            wrapper.before_call.write_code("}")
632
 
                
633
 
 
 
670
            wrapper.before_call.write_code("}") # closes if (typeid(*(%s)) == typeid(%s))\n{
 
671
            wrapper.build_params.add_parameter("N", [py_name])
 
672
            
634
673
 
635
674
 
636
675
def _add_ward(wrapper, custodian, ward):
677
716
        """
678
717
        if ctype == self.cpp_class.name:
679
718
            ctype = self.cpp_class.full_name
680
 
        super(CppClassPtrReturnValue, self).__init__(ctype)
681
 
        self.is_const = is_const
682
 
        if custodian is None and caller_owns_return is None:
683
 
            raise TypeConfigurationError("caller_owns_return not given")
 
719
        super(CppClassPtrReturnValue, self).__init__(ctype, is_const=is_const)
 
720
        if custodian is None:
 
721
            if caller_owns_return is None:
 
722
                if self.type_traits.target_is_const:
 
723
                    caller_owns_return = False
 
724
                else:
 
725
                    raise TypeConfigurationError("caller_owns_return not given")
 
726
        else:
 
727
            if caller_owns_return is not None:
 
728
                raise TypeConfigurationError("caller_owns_return should not given together with custodian")
684
729
        self.custodian = custodian
685
730
        if custodian is None:
686
731
            self.caller_owns_return = caller_owns_return
756
801
                else:
757
802
                    ## The PyObject gets a new reference to the same obj
758
803
                    self.cpp_class.memory_policy.write_incref(wrapper.after_call, value)
759
 
                    if self.is_const:
 
804
                    if self.type_traits.target_is_const:
760
805
                        wrapper.after_call.write_code("%s->obj = (%s*) (%s);" %
761
806
                                                      (py_name, self.cpp_class.full_name, value))
762
807
                    else:
764
809
        ## closes def write_create_new_wrapper():
765
810
 
766
811
        if self.cpp_class.helper_class is None:
767
 
            write_create_new_wrapper()
 
812
            try:
 
813
                self.cpp_class.wrapper_registry.write_lookup_wrapper(
 
814
                    wrapper.after_call, self.cpp_class.pystruct, py_name, value)
 
815
            except NotSupportedError:
 
816
                write_create_new_wrapper()
 
817
                self.cpp_class.wrapper_registry.write_register_new_wrapper(
 
818
                    wrapper.after_call, py_name, "%s->obj" % py_name)
 
819
            else:
 
820
                wrapper.after_call.write_code("if (%s == NULL) {" % py_name)
 
821
                wrapper.after_call.indent()
 
822
                write_create_new_wrapper()
 
823
                self.cpp_class.wrapper_registry.write_register_new_wrapper(
 
824
                    wrapper.after_call, py_name, "%s->obj" % py_name)
 
825
                wrapper.after_call.unindent()
 
826
 
 
827
                # If we are already referencing the existing python wrapper,
 
828
                # we do not need a reference to the C++ object as well.
 
829
                if self.caller_owns_return and \
 
830
                        isinstance(self.cpp_class.memory_policy, cppclass.ReferenceCountingPolicy):
 
831
                    wrapper.after_call.write_code("} else {")
 
832
                    wrapper.after_call.indent()
 
833
                    self.cpp_class.memory_policy.write_decref(wrapper.after_call, value)
 
834
                    wrapper.after_call.unindent()
 
835
                    wrapper.after_call.write_code("}")
 
836
                else:
 
837
                    wrapper.after_call.write_code("}")            
768
838
        else:
769
839
            wrapper.after_call.write_code("if (typeid(*(%s)) == typeid(%s))\n{"
770
840
                                          % (value, self.cpp_class.helper_class.name))
771
841
            wrapper.after_call.indent()
772
842
 
773
 
            if self.is_const:
 
843
            if self.type_traits.target_is_const:
774
844
                const_cast_value = "const_cast<%s *>(%s) " % (self.cpp_class.full_name, value)
775
845
            else:
776
846
                const_cast_value = value
780
850
                   self.cpp_class.helper_class.name, const_cast_value))
781
851
 
782
852
            wrapper.after_call.write_code("%s->obj = %s;" % (py_name, const_cast_value))
 
853
        
 
854
            # We are already referencing the existing python wrapper,
 
855
            # so we do not need a reference to the C++ object as well.
 
856
            if self.caller_owns_return and \
 
857
                    isinstance(self.cpp_class.memory_policy, cppclass.ReferenceCountingPolicy):
 
858
                self.cpp_class.memory_policy.write_decref(wrapper.after_call, value)
 
859
 
783
860
            wrapper.after_call.write_code("Py_INCREF(%s);" % py_name)
784
861
            wrapper.after_call.unindent()
785
 
            wrapper.after_call.write_code("} else {")
 
862
            wrapper.after_call.write_code("} else {") # if (typeid(*(%s)) == typeid(%s)) { ...
786
863
            wrapper.after_call.indent()
787
 
            write_create_new_wrapper()
 
864
 
 
865
            # creater new wrapper or reference existing one
 
866
            try:
 
867
                self.cpp_class.wrapper_registry.write_lookup_wrapper(
 
868
                    wrapper.after_call, self.cpp_class.pystruct, py_name, value)
 
869
            except NotSupportedError:
 
870
                write_create_new_wrapper()
 
871
                self.cpp_class.wrapper_registry.write_register_new_wrapper(
 
872
                    wrapper.after_call, py_name, "%s->obj" % py_name)
 
873
            else:
 
874
                wrapper.after_call.write_code("if (%s == NULL) {" % py_name)
 
875
                wrapper.after_call.indent()
 
876
                write_create_new_wrapper()
 
877
                self.cpp_class.wrapper_registry.write_register_new_wrapper(
 
878
                    wrapper.after_call, py_name, "%s->obj" % py_name)
 
879
                wrapper.after_call.unindent()
 
880
 
 
881
                if self.caller_owns_return and \
 
882
                        isinstance(self.cpp_class.memory_policy, cppclass.ReferenceCountingPolicy):
 
883
                    wrapper.after_call.write_code("} else {")
 
884
                    wrapper.after_call.indent()
 
885
                    # If we are already referencing the existing python wrapper,
 
886
                    # we do not need a reference to the C++ object as well.
 
887
                    self.cpp_class.memory_policy.write_decref(wrapper.after_call, value)
 
888
                    wrapper.after_call.unindent()
 
889
                    wrapper.after_call.write_code("}")
 
890
                else:
 
891
                    wrapper.after_call.write_code("}")            
 
892
 
 
893
 
788
894
            wrapper.after_call.unindent()
789
 
            wrapper.after_call.write_code("}")
790
 
                
 
895
            wrapper.after_call.write_code("}") # closes: if (typeid(*(%s)) == typeid(%s)) { ... } else { ...
 
896
            
791
897
        wrapper.build_params.add_parameter("N", [py_name], prepend=True)
792
898
        
793
899
        if self.custodian is None:
823
929
            else:
824
930
                ## the caller gets a new reference to the same obj
825
931
                self.cpp_class.memory_policy.write_incref(wrapper.after_call, value)
826
 
                if self.is_const:
 
932
                if self.type_traits.target_is_const:
827
933
                    wrapper.after_call.write_code(
828
934
                        "%s = const_cast< %s* >(%s);" %
829
935
                        (self.value, self.cpp_class.full_name, value))