Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
CPPConstructor.cxx
Go to the documentation of this file.
1// Bindings
2#include "CPyCppyy.h"
3#include "CPPConstructor.h"
4#include "CPPInstance.h"
5#include "Executors.h"
6#include "MemoryRegulator.h"
7#include "ProxyWrappers.h"
8#include "PyStrings.h"
9
11
12// Standard
13#include <string>
14
15
16//- protected members --------------------------------------------------------
18{
19// pick up special case new object executor
20 executor = CreateExecutor("__init__");
21 return true;
22}
23
24//- public members -----------------------------------------------------------
26{
27// GetMethod() may return an empty function if this is just a special case place holder
28 const std::string& clName = Cppyy::GetFinalName(this->GetScope());
29 return CPyCppyy_PyText_FromFormat("%s::%s%s",
30 clName.c_str(), clName.c_str(), this->GetMethod() ? this->GetSignatureString().c_str() : "()");
31}
32
33//----------------------------------------------------------------------------
36{
37// C++ reflection tooling for constructors.
38
39 if (request == Cppyy::Reflex::RETURN_TYPE) {
40 std::string fn = Cppyy::GetScopedFinalName(this->GetScope());
42 return CreateScopeProxy(fn);
44 return CPyCppyy_PyText_FromString(fn.c_str());
45 }
46
47 return PyCallable::Reflex(request, format);
48}
49
50//----------------------------------------------------------------------------
52 CPPInstance*& self, PyObject* args, PyObject* kwds, CallContext* ctxt)
53{
54// setup as necessary
55 if (fArgsRequired == -1 && !this->Initialize(ctxt))
56 return nullptr; // important: 0, not Py_None
57
58// fetch self, verify, and put the arguments in usable order
59 if (!(args = this->PreProcessArgs(self, args, kwds)))
60 return nullptr;
61
62// verify existence of self (i.e. tp_new called)
63 if (!self) {
64 PyErr_Print();
65 PyErr_SetString(PyExc_ReferenceError, "no python object allocated");
66 return nullptr;
67 }
68
69 if (self->GetObject()) {
70 Py_DECREF(args);
71 PyErr_SetString(PyExc_ReferenceError,
72 "object already constructed; use __assign__ instead of __init__");
73 return nullptr;
74 }
75
76// perform the call, nullptr 'this' makes the other side allocate the memory
77 Cppyy::TCppScope_t disp = self->ObjectIsA(false /* check_smart */);
78 ptrdiff_t address = 0;
79 if (GetScope() != disp) {
80 // happens for Python derived types, which have a dispatcher inserted that
81 // is not otherwise user-visible: call it instead
82 // first, check whether we at least had a proper meta class, or whether that
83 // was also replaced user-side
84 if (!GetScope() || !disp) {
85 PyErr_SetString(PyExc_TypeError, "can not construct incomplete C++ class");
86 return nullptr;
87 }
88
89 // get the dispatcher class
90 PyObject* dispproxy = CPyCppyy::GetScopeProxy(disp);
91 if (!dispproxy) {
92 PyErr_SetString(PyExc_TypeError, "dispatcher proxy was never created");
93 return nullptr;
94 }
95
96 PyObject* pyobj = PyObject_Call(dispproxy, args, kwds);
97 if (!pyobj)
98 return nullptr;
99
100 // retrieve the actual pointer, take over control, and set m_self
101 address = (ptrdiff_t)((CPPInstance*)pyobj)->GetObject();
102 if (address) {
103 ((CPPInstance*)pyobj)->CppOwns();
104 PyObject* res = PyObject_CallMethodObjArgs(
105 dispproxy, PyStrings::gDispInit, pyobj, (PyObject*)self, nullptr);
106 Py_XDECREF(res);
107 }
108 Py_DECREF(pyobj);
109 Py_DECREF(dispproxy);
110
111 } else {
112 // translate the arguments
113 if (!this->ConvertAndSetArgs(args, ctxt)) {
114 Py_DECREF(args);
115 return nullptr;
116 }
117
118 address = (ptrdiff_t)this->Execute(nullptr, 0, ctxt);
119 }
120
121// done with filtered args
122 Py_DECREF(args);
123
124// return object if successful, lament if not
125 if (address) {
126 Py_INCREF(self);
127
128 // note: constructors are no longer set to take ownership by default; instead that is
129 // decided by the method proxy (which carries a creator flag) upon return
130 self->Set((void*)address);
131
132 // TODO: consistent up or down cast ...
134
135 // handling smart types this way is deeply fugly, but if CPPInstance sets the proper
136 // types in op_new first, then the wrong init is called
137 if (((CPPClass*)Py_TYPE(self))->fFlags & CPPScope::kIsSmart) {
139 if (pyclass) {
140 self->SetSmart((PyObject*)Py_TYPE(self));
141 Py_DECREF((PyObject*)Py_TYPE(self));
142 Py_SET_TYPE(self, (PyTypeObject*)pyclass);
143 }
144 }
145
146 // done with self
147 Py_DECREF(self);
148
149 Py_RETURN_NONE; // by definition
150 }
151
152 if (!PyErr_Occurred()) // should be set, otherwise write a generic error msg
153 PyErr_SetString(PyExc_TypeError, const_cast<char*>(
154 (Cppyy::GetScopedFinalName(GetScope()) + " constructor failed").c_str()));
155
156// do not throw an exception, nullptr might trigger the overload handler to
157// choose a different constructor, which if all fails will throw an exception
158 return nullptr;
159}
160
161
162//----------------------------------------------------------------------------
164 CPPInstance*& self, PyObject* args, PyObject* kwds, CallContext* ctxt)
165{
166// do not allow instantiation of abstract classes
167 if (self && GetScope() != self->ObjectIsA()) {
168 // happens if a dispatcher is inserted; allow constructor call
169 return CPPConstructor::Call(self, args, kwds, ctxt);
170 }
171
172 PyErr_Format(PyExc_TypeError, "cannot instantiate abstract class \'%s\'"
173 " (from derived classes, use super() instead)",
174 Cppyy::GetScopedFinalName(this->GetScope()).c_str());
175 return nullptr;
176}
177
178//----------------------------------------------------------------------------
181{
182// do not allow instantiation of namespaces
183 PyErr_Format(PyExc_TypeError, "cannot instantiate namespace \'%s\'",
184 Cppyy::GetScopedFinalName(this->GetScope()).c_str());
185 return nullptr;
186}
187
188//----------------------------------------------------------------------------
191{
192// do not allow instantiation of incomplete (forward declared) classes)
193 PyErr_Format(PyExc_TypeError, "cannot instantiate incomplete class \'%s\'",
194 Cppyy::GetScopedFinalName(this->GetScope()).c_str());
195 return nullptr;
196}
#define Py_TYPE(ob)
Definition CPyCppyy.h:217
#define Py_SET_TYPE(ob, type)
Definition CPyCppyy.h:311
#define CPyCppyy_PyText_FromFormat
Definition CPyCppyy.h:101
#define Py_RETURN_NONE
Definition CPyCppyy.h:289
#define CPyCppyy_PyText_FromString
Definition CPyCppyy.h:102
Cppyy::TCppType_t fUnderlyingType
_object PyObject
std::ios_base::fmtflags fFlags
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t format
virtual PyObject * Call(CPPInstance *&, PyObject *, PyObject *, CallContext *=nullptr)
virtual PyObject * GetDocString()
virtual bool InitExecutor_(Executor *&, CallContext *ctxt=nullptr)
virtual PyObject * Reflex(Cppyy::Reflex::RequestId_t, Cppyy::Reflex::FormatId_t=Cppyy::Reflex::OPTIMAL)
virtual PyObject * Call(CPPInstance *&self, PyObject *args, PyObject *kwds, CallContext *ctxt=nullptr)
virtual PyObject * Call(CPPInstance *&, PyObject *, PyObject *, CallContext *=nullptr)
void Set(void *address, EFlags flags=kDefault)
Definition CPPInstance.h:88
void SetSmart(PyObject *smart_type)
Cppyy::TCppType_t ObjectIsA(bool check_smart=true) const
virtual PyObject * Call(CPPInstance *&, PyObject *, PyObject *, CallContext *=nullptr)
static bool RegisterPyObject(CPPInstance *pyobj, void *cppobj)
virtual PyObject * Reflex(Cppyy::Reflex::RequestId_t request, Cppyy::Reflex::FormatId_t format=Cppyy::Reflex::OPTIMAL)
Definition PyCallable.h:23
PyObject * gDispInit
Definition PyStrings.cxx:58
PyObject * GetScopeProxy(Cppyy::TCppScope_t)
CPYCPPYY_EXTERN Executor * CreateExecutor(const std::string &name)
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
const RequestId_t RETURN_TYPE
Definition Reflex.h:17
const FormatId_t AS_STRING
Definition Reflex.h:23
const FormatId_t OPTIMAL
Definition Reflex.h:21
const FormatId_t AS_TYPE
Definition Reflex.h:22
void * TCppObject_t
Definition cpp_cppyy.h:21
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
size_t TCppScope_t
Definition cpp_cppyy.h:18
RPY_EXPORTED std::string GetFinalName(TCppType_t type)