23 code <<
" " << retType <<
" " << mtCppName <<
"(";
27 std::vector<std::string> argtypes; argtypes.reserve(nArgs);
30 if (i != 0) code <<
", ";
31 code << argtypes.back() <<
" arg" << i;
42 code <<
" PyObject* iself = (PyObject*)_internal_self;\n"
43 " if (!iself || iself == Py_None) {\n"
44 " PyErr_Warn(PyExc_RuntimeWarning, (char*)\"Call attempted on deleted python-side proxy\");\n"
46 if (retType !=
"void") {
47 if (retType.back() !=
'*')
54 " Py_INCREF(iself);\n";
57 Utility::ConstructCallbackPreamble(retType, argtypes, code);
60#if PY_VERSION_HEX < 0x03000000
61 code <<
" PyObject* mtPyName = PyString_FromString(\"" << mtCppName <<
"\");\n"
63 code <<
" PyObject* mtPyName = PyUnicode_FromString(\"" << mtCppName <<
"\");\n"
65 " PyObject* pyresult = PyObject_CallMethodObjArgs(iself, mtPyName";
67 code <<
", pyargs[" << i <<
"]";
68 code <<
", NULL);\n Py_DECREF(mtPyName);\n Py_DECREF(iself);\n";
71 Utility::ConstructCallbackReturn(retType, (
int)nArgs, code);
78 btype(t), bname(bn), bname_scoped(bns) {}
81 std::string bname_scoped;
84 typedef std::vector<BaseInfo> BaseInfos_t;
85 typedef std::vector<Cppyy::TCppMethod_t> Ctors_t;
86 typedef std::vector<Ctors_t> AllCtors_t;
87 typedef std::vector<std::pair<Cppyy::TCppMethod_t, size_t>> CtorInfos_t;
91 const std::string& derivedName,
const BaseInfos_t& base_infos,
const AllCtors_t& ctors,
92 std::ostringstream& code,
const CtorInfos_t& methods = CtorInfos_t{},
size_t idx = 0)
94 if (idx < ctors.size()) {
95 for (
const auto& method : ctors[idx]) {
98 for (
size_t i = argsmin; i <= argsmax; ++i) {
99 CtorInfos_t methods1{methods};
100 methods1.emplace_back(method, i);
106 code <<
" " << derivedName <<
"(";
109 std::vector<size_t> arg_tots; arg_tots.reserve(methods.size());
110 for (Ctors_t::size_type i = 0; i < methods.size(); ++i) {
111 const auto& cinfo = methods[i];
112 if (i != 0 && (arg_tots.back() || 1 < arg_tots.size())) code <<
", ";
113 size_t nArgs = cinfo.second;
114 arg_tots.push_back(i == 0 ? nArgs : nArgs+arg_tots.back());
116 if (i != 0) code <<
"__cppyy_internal::Sep*";
117 size_t offset = (i != 0 ? arg_tots[i-1] : 0);
118 for (
size_t j = 0; j < nArgs; ++j) {
119 if (i != 0 || j != 0) code <<
", ";
126 for (BaseInfos_t::size_type i = 0; i < base_infos.size(); ++i) {
127 if (i != 0) code <<
", ";
128 code << base_infos[i].bname <<
"(";
129 size_t first = (i != 0 ? arg_tots[i-1] : 0);
130 for (
size_t j = first; j < arg_tots[i]; ++j) {
131 if (j != first) code <<
", ";
134 if (isRValue) code <<
"std::move(";
136 if (isRValue) code <<
")";
146using namespace Cppyy;
149std::vector<TCppIndex_t> FindBaseMethod(
TCppScope_t tbase,
const std::string mtCppName)
152 std::vector<TCppIndex_t>
result;
157 result = FindBaseMethod(
b, mtCppName);
172 if (!PyTuple_Check(bases) || !PyTuple_GET_SIZE(bases) || !dct || !PyDict_Check(dct)) {
173 err <<
"internal error: expected tuple of bases and proper dictionary";
177 if (!Utility::IncludePython()) {
178 err <<
"failed to include Python.h";
183 const Py_ssize_t nBases = PyTuple_GET_SIZE(bases);
184 BaseInfos_t base_infos; base_infos.reserve(nBases);
185 for (
Py_ssize_t ibase = 0; ibase < nBases; ++ibase) {
192 err <<
"base class is incomplete";
203 PyErr_Warn(PyExc_RuntimeWarning, (
char*)(
"class \""+bname+
"\" has no virtual destructor").c_str());
206 base_infos.emplace_back(
211 bool isDeepHierarchy = klass->
fCppType && base_infos.front().btype != klass->
fCppType;
215 static int counter = 0;
216 std::ostringstream osname;
217 osname <<
"Dispatcher" << ++counter;
218 const std::string& derivedName = osname.str();
221 std::ostringstream code;
224 code <<
"namespace __cppyy_internal {\n"
225 <<
"class " << derivedName <<
" : ";
226 for (BaseInfos_t::size_type ibase = 0; ibase < base_infos.size(); ++ibase) {
227 if (ibase != 0) code <<
", ";
228 code <<
"public ::" << base_infos[ibase].bname_scoped;
231 if (!isDeepHierarchy)
232 code <<
"protected:\n CPyCppyy::DispatchPtr _internal_self;\n";
239 if (PyMapping_HasKeyString(dct, (
char*)
"__destruct__")) {
240 code <<
" virtual ~" << derivedName <<
"() {\n"
241 " PyObject* iself = (PyObject*)_internal_self;\n"
242 " if (!iself || iself == Py_None)\n"
244 " Py_INCREF(iself);\n"
245 " PyObject* mtPyName = PyUnicode_FromString(\"__destruct__\");\n"
246 " PyObject* pyresult = PyObject_CallMethodObjArgs(iself, mtPyName, NULL);\n"
247 " Py_DECREF(mtPyName);\n Py_DECREF(iself);\n";
251 code <<
" if (!pyresult) PyErr_Print();\n"
252 " else { Py_DECREF(pyresult); }\n"
255 code <<
" virtual ~" << derivedName <<
"() {}\n";
260 PyObject* items = PyDict_Items(dct);
261 for (
Py_ssize_t i = 0; i < PyList_GET_SIZE(items); ++i) {
262 PyObject*
value = PyTuple_GET_ITEM(PyList_GET_ITEM(items, i), 1);
263 if (PyCallable_Check(
value))
264 PyDict_SetItem(clbs, PyTuple_GET_ITEM(PyList_GET_ITEM(items, i), 0),
value);
267 if (PyDict_DelItem(clbs, PyStrings::gInit) != 0)
272 std::set<std::string> protected_names;
275 int has_default = 0, has_cctor = 0, has_ctors = 0, has_tmpl_ctors = 0;
276 AllCtors_t ctors{base_infos.size()};
277 for (BaseInfos_t::size_type ibase = 0; ibase < base_infos.size(); ++ibase) {
278 const auto& binfo = base_infos[ibase];
281 bool cctor_found =
false, default_found =
false, any_ctor_found =
false;
286 any_ctor_found =
true;
289 if (nreq == 0) default_found =
true;
290 else if (!cctor_found && nreq == 1) {
292 if (TypeManip::compound(argtype) ==
"&" && TypeManip::clean_type(argtype,
false) == binfo.bname_scoped)
295 ctors[ibase].push_back(method);
302 int contains = PyDict_Contains(dct, key);
303 if (contains == -1) PyErr_Clear();
310 protected_names.insert(mtCppName);
315 if (i != 0) code <<
", ";
320 code <<
"{\n return " << binfo.bname <<
"::" << mtCppName <<
"(";
322 if (i != 0) code <<
", ";
333 if (PyDict_DelItem(clbs, key) != 0)
339 if (base_infos.size() == 1) {
343 any_ctor_found =
true;
351 if (cctor_found || (!cctor_found && !any_ctor_found)) has_cctor += 1;
352 if (default_found || (!default_found && !any_ctor_found)) has_default += 1;
353 if (any_ctor_found && !has_tmpl_ctors) has_ctors += 1;
357 for (
const auto& binfo : base_infos) {
358 if (PyDict_Size(clbs)) {
360 for (
size_t ibase = 0; ibase < nbases; ++ibase) {
365 for (
Py_ssize_t i = 0; i < PyList_GET_SIZE(keys); ++i) {
367 PyObject* key = PyList_GET_ITEM(keys, i);
369 const auto&
v = FindBaseMethod(tbase, mtCppName);
373 if (PyDict_DelItem(clbs, key) != 0) PyErr_Clear();
390 if (1 < nBases && (!has_ctors || has_default == nBases))
391 code <<
" " << derivedName <<
"() {}\n";
392 if (has_cctor == nBases) {
393 code <<
" " << derivedName <<
"(const " << derivedName <<
"& other) : ";
394 for (BaseInfos_t::size_type ibase = 0; ibase < base_infos.size(); ++ibase) {
395 if (ibase != 0) code <<
", ";
396 code << base_infos[ibase].bname <<
"(other)";
398 if (!isDeepHierarchy)
399 code <<
", _internal_self(other._internal_self, this)";
402 if (has_tmpl_ctors && base_infos.size() == 1) {
404 code <<
" template<typename ...Args>\n " << derivedName <<
"(Args... args) : "
405 << base_infos[0].bname <<
"(args...) {}\n";
411 bool setPublic =
false;
412 for (
const auto& binfo : base_infos) {
417 if (dm_name !=
"_internal_self") {
419 protected_names.insert(dname);
424 code <<
" using " << binfo.bname <<
"::" << dname <<
";\n";
431 BaseInfos_t::size_type disp_inited = 0;
432 code <<
"public:\n static void _init_dispatchptr(" << derivedName <<
"* inst, PyObject* self) {\n";
433 if (1 < base_infos.size()) {
434 for (
const auto& binfo : base_infos) {
436 code <<
" " << binfo.bname <<
"::_init_dispatchptr(inst, self);\n";
447 if (disp_inited != base_infos.size())
448 code <<
" new ((void*)&inst->_internal_self) CPyCppyy::DispatchPtr{self, true};\n";
452 code <<
"\n static PyObject* _get_dispatch(" << derivedName <<
"* inst) {\n"
453 " PyObject* res = (PyObject*)inst->_internal_self;\n"
454 " Py_XINCREF(res); return res;\n }";
461 err <<
"failed to compile the dispatcher code";
469 err <<
"failed to retrieve the internal dispatcher";
477 unsigned int flags = (
unsigned int)(klass->
fFlags & CPPScope::kIsMultiCross);
479 if (flags) ((
CPPScope*)disp_proxy)->fFlags |= CPPScope::kIsMultiCross;
480 ((
CPPScope*)disp_proxy)->fFlags |= CPPScope::kIsPython;
485 for (
const auto&
name : protected_names) {
486 PyObject* disp_dct = PyObject_GetAttr(disp_proxy, PyStrings::gDict);
487#if PY_VERSION_HEX < 0x30d00f0
488 PyObject* pyf = PyMapping_GetItemString(disp_dct, (
char*)
name.c_str());
491 PyMapping_GetOptionalItemString(disp_dct, (
char*)
name.c_str(), &pyf);
494 PyObject_SetAttrString((
PyObject*)klass, (
char*)
name.c_str(), pyf);
500 Py_XDECREF(disp_proxy);
#define CPyCppyy_PyText_AsString
#define CPyCppyy_PyText_FromString
static void InjectMethod(Cppyy::TCppMethod_t method, const std::string &mtCppName, std::ostringstream &code)
static void build_constructors(const std::string &derivedName, const BaseInfos_t &base_infos, const AllCtors_t &ctors, std::ostringstream &code, const CtorInfos_t &methods=CtorInfos_t{}, size_t idx=0)
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 offset
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 result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Cppyy::TCppType_t fCppType
std::string remove_const(const std::string &cppname)
std::string compound(const std::string &name)
PyObject * CreateScopeProxy(Cppyy::TCppScope_t, const unsigned flags=0)
bool CPPScope_Check(T *object)
bool InsertDispatcher(CPPScope *klass, PyObject *bases, PyObject *dct, std::ostringstream &err)
RPY_EXPORTED TCppIndex_t GetNumTemplatedMethods(TCppScope_t scope, bool accept_namespace=false)
RPY_EXPORTED TCppIndex_t GetMethodReqArgs(TCppMethod_t)
RPY_EXPORTED std::vector< TCppIndex_t > GetMethodIndicesFromName(TCppScope_t scope, const std::string &name)
RPY_EXPORTED TCppIndex_t GetNumDatamembers(TCppScope_t scope, bool accept_namespace=false)
RPY_EXPORTED std::string GetMethodName(TCppMethod_t)
RPY_EXPORTED bool Compile(const std::string &code, bool silent=false)
RPY_EXPORTED bool IsProtectedData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED bool IsConstructor(TCppMethod_t method)
RPY_EXPORTED TCppIndex_t GetNumMethods(TCppScope_t scope, bool accept_namespace=false)
RPY_EXPORTED TCppIndex_t GetMethodNumArgs(TCppMethod_t)
RPY_EXPORTED std::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
RPY_EXPORTED bool IsNamespace(TCppScope_t scope)
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
RPY_EXPORTED std::string GetMethodArgType(TCppMethod_t, TCppIndex_t iarg)
RPY_EXPORTED TCppIndex_t GetDatamemberIndex(TCppScope_t scope, const std::string &name)
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RPY_EXPORTED bool HasVirtualDestructor(TCppType_t type)
RPY_EXPORTED bool IsConstMethod(TCppMethod_t)
RPY_EXPORTED bool IsTemplatedConstructor(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED TCppIndex_t GetNumBases(TCppType_t type)
RPY_EXPORTED std::string GetMethodResultType(TCppMethod_t)
RPY_EXPORTED std::string GetFinalName(TCppType_t type)
RPY_EXPORTED std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED bool IsPublicMethod(TCppMethod_t method)
RPY_EXPORTED bool IsProtectedMethod(TCppMethod_t method)