40
40
cpp_class = cppclass.CppClass('dummy') # CppClass instance
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
145
145
self.cpp_class.write_create_instance(wrapper.before_call,
146
146
"%s->obj" % self.py_name,
148
self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, self.py_name,
149
"%s->obj" % self.py_name)
149
151
wrapper.build_params.add_parameter("N", [self.py_name])
181
183
'*((%s *) %s)->obj' % (self.cpp_class.pystruct, self.py_name))
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,
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])
301
305
self.cpp_class.write_create_instance(wrapper.before_call,
302
306
"%s->obj" % self.py_name,
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])
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.
317
if self.type_traits.target_is_const:
312
318
value = "(%s*) (&(%s))" % (self.cpp_class.full_name, self.value)
314
320
value = "&(%s)" % self.value
330
336
self.cpp_class.write_create_instance(wrapper.after_call,
331
337
"%s->obj" % self.py_name,
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('}')
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)
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,
380
self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.after_call, py_name,
374
382
wrapper.build_params.add_parameter("N", [py_name], prepend=True)
376
384
def convert_python_to_c(self, wrapper):
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
447
raise TypeConfigurationError("transfer_ownership parameter missing")
437
448
self.transfer_ownership = transfer_ownership
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])
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,
563
wrapper.build_params.add_parameter("N", [self.py_name])
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.
579
if self.type_traits.target_is_const:
571
580
unconst_value = "(%s*) (%s)" % (self.cpp_class.full_name, value)
573
582
unconst_value = value
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)
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))
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():
605
613
if self.cpp_class.helper_class is None:
606
write_create_new_wrapper()
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,
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,
627
wrapper.before_call.unindent()
628
wrapper.before_call.write_code('}')
629
wrapper.build_params.add_parameter("N", [py_name])
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()
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()
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)
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,
666
wrapper.before_call.unindent()
667
wrapper.before_call.write_code('}') # closes if (%s == NULL)
630
669
wrapper.before_call.unindent()
631
wrapper.before_call.write_code("}")
670
wrapper.before_call.write_code("}") # closes if (typeid(*(%s)) == typeid(%s))\n{
671
wrapper.build_params.add_parameter("N", [py_name])
636
675
def _add_ward(wrapper, custodian, ward):
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
725
raise TypeConfigurationError("caller_owns_return not given")
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
764
809
## closes def write_create_new_wrapper():
766
811
if self.cpp_class.helper_class is None:
767
write_create_new_wrapper()
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)
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()
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("}")
837
wrapper.after_call.write_code("}")
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()
843
if self.type_traits.target_is_const:
774
844
const_cast_value = "const_cast<%s *>(%s) " % (self.cpp_class.full_name, value)
776
846
const_cast_value = value
780
850
self.cpp_class.helper_class.name, const_cast_value))
782
852
wrapper.after_call.write_code("%s->obj = %s;" % (py_name, const_cast_value))
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)
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()
865
# creater new wrapper or reference existing one
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)
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()
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("}")
891
wrapper.after_call.write_code("}")
788
894
wrapper.after_call.unindent()
789
wrapper.after_call.write_code("}")
895
wrapper.after_call.write_code("}") # closes: if (typeid(*(%s)) == typeid(%s)) { ... } else { ...
791
897
wrapper.build_params.add_parameter("N", [py_name], prepend=True)
793
899
if self.custodian is None:
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)
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))