23 code <<
" " << retType <<
" " << mtCppName <<
"(";
27 std::vector<std::string> argtypes; argtypes.reserve(nArgs);
30 if (i != 0) code <<
", ";
31 code << argtypes.back() <<
" arg" << i;
38 Utility::ConstructCallbackPreamble(retType, argtypes, code);
41#if PY_VERSION_HEX < 0x03000000
42 code <<
" PyObject* mtPyName = PyString_FromString(\"" << mtCppName <<
"\");\n"
44 code <<
" PyObject* mtPyName = PyUnicode_FromString(\"" << mtCppName <<
"\");\n"
46 " PyObject* pyresult = PyObject_CallMethodObjArgs((PyObject*)_internal_self, mtPyName";
49 code <<
", pyargs[" << i <<
"]";
50 code <<
", NULL);\n Py_DECREF(mtPyName);\n";
53 Utility::ConstructCallbackReturn(retType, nArgs, code);
60 btype(t), bname(bn), bname_scoped(bns) {}
63 std::string bname_scoped;
66 typedef std::vector<BaseInfo> BaseInfos_t;
74 if (!PyTuple_Check(bases) || !PyTuple_GET_SIZE(bases) || !dct || !PyDict_Check(dct)) {
75 err <<
"internal error: expected tuple of bases and proper dictionary";
79 if (!Utility::IncludePython()) {
80 err <<
"failed to include Python.h";
84 const Py_ssize_t nBases = PyTuple_GET_SIZE(bases);
85 BaseInfos_t base_infos; base_infos.reserve(nBases);
86 for (
Py_ssize_t ibase = 0; ibase < nBases; ++ibase) {
87 auto currentBase = PyTuple_GET_ITEM(bases, ibase);
94 err <<
"base class is incomplete";
105 PyErr_Warn(PyExc_RuntimeWarning, (
char*)(
"class \""+bname+
"\" has no virtual destructor").c_str());
108 base_infos.emplace_back(
115 err <<
"multi cross-inheritance not supported";
119 const auto& binfo = base_infos[0];
121 const std::string& baseName = binfo.bname;
122 const std::string& baseNameScoped = binfo.bname_scoped;
128 static int counter = 0;
129 std::ostringstream osname;
130 osname <<
"Dispatcher" << ++counter;
131 const std::string& derivedName = osname.str();
134 std::ostringstream code;
137 code <<
"namespace __cppyy_internal {\n"
138 <<
"class " << derivedName <<
" : public ::" << baseNameScoped <<
" {\n";
139 if (!isDeepHierarchy)
140 code <<
"protected:\n CPyCppyy::DispatchPtr _internal_self;\n";
144 code <<
" virtual ~" << derivedName <<
"() {}\n";
149 PyObject* items = PyDict_Items(dct);
150 for (
Py_ssize_t i = 0; i < PyList_GET_SIZE(items); ++i) {
151 PyObject* value = PyTuple_GET_ITEM(PyList_GET_ITEM(items, i), 1);
152 if (PyCallable_Check(value))
153 PyDict_SetItem(clbs, PyTuple_GET_ITEM(PyList_GET_ITEM(items, i), 0), value);
156 if (PyDict_DelItem(clbs, PyStrings::gInit) != 0)
161 std::set<std::string> protected_names;
164 bool has_default =
false;
165 bool has_cctor =
false;
166 bool has_constructors =
false;
172 has_constructors =
true;
176 else if (!has_cctor && nreq == 1) {
178 if (Utility::Compound(argtype) ==
"&" && TypeManip::clean_type(argtype,
false) == baseNameScoped)
186 int contains = PyDict_Contains(dct, key);
187 if (contains == -1) PyErr_Clear();
194 protected_names.insert(mtCppName);
199 if (i != 0) code <<
", ";
204 code <<
"{\n return " << baseName <<
"::" << mtCppName <<
"(";
206 if (i != 0) code <<
", ";
217 if (PyDict_DelItem(clbs, key) != 0)
223 if (PyDict_Size(clbs)) {
225 for (
size_t ibase = 0; ibase < nbases; ++ibase) {
230 for (
Py_ssize_t i = 0; i < PyList_GET_SIZE(keys); ++i) {
232 PyObject* key = PyList_GET_ITEM(keys, i);
238 if (PyDict_DelItem(clbs, key) != 0) PyErr_Clear();
247 code <<
" using " << baseName <<
"::" << baseName <<
";\n";
252 if (has_default || !has_constructors)
253 code <<
" " << derivedName <<
"() {}\n";
254 if (has_default || has_cctor || !has_constructors) {
255 code <<
" " << derivedName <<
"(const " << derivedName <<
"& other)";
257 code <<
" : " << baseName <<
"(other)";
258 if (!isDeepHierarchy) {
259 if (has_cctor) code <<
", ";
261 code <<
"_internal_self(other._internal_self, this)";
270 if (nData) code <<
"public:\n";
274 if (dm_name !=
"_internal_self") {
275 protected_names.insert(dm_name);
276 code <<
" using " << baseName <<
"::" << dm_name <<
";\n";
282 code <<
"public:\n static void _init_dispatchptr(" << derivedName <<
"* inst, PyObject* self) {\n"
283 " new ((void*)&inst->_internal_self) CPyCppyy::DispatchPtr{self};\n"
291 err <<
"failed to compile the dispatcher code";
299 err <<
"failed to retrieve the internal dispatcher";
312 for (
const auto&
name : protected_names) {
313 PyObject* disp_dct = PyObject_GetAttr(disp_proxy, PyStrings::gDict);
314 PyObject* pyf = PyMapping_GetItemString(disp_dct, (
char*)
name.c_str());
316 PyObject_SetAttrString((
PyObject*)klass, (
char*)
name.c_str(), pyf);
322 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)
Cppyy::TCppType_t fCppType
Set of helper functions that are invoked from the pythonizors, on the Python side.
bool CPPScope_Check(T *object)
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
bool InsertDispatcher(CPPScope *klass, PyObject *bases, PyObject *dct, std::ostringstream &err)
RPY_EXPORTED std::vector< TCppIndex_t > GetMethodIndicesFromName(TCppScope_t scope, const std::string &name)
RPY_EXPORTED bool Compile(const std::string &code)
RPY_EXPORTED bool IsProtectedMethod(TCppMethod_t method)
RPY_EXPORTED bool IsProtectedData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED bool IsConstructor(TCppMethod_t method)
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED std::string GetFinalName(TCppType_t type)
RPY_EXPORTED bool IsPublicMethod(TCppMethod_t method)
RPY_EXPORTED TCppIndex_t GetMethodReqArgs(TCppMethod_t)
RPY_EXPORTED std::string GetMethodName(TCppMethod_t)
RPY_EXPORTED TCppIndex_t GetNumBases(TCppType_t type)
RPY_EXPORTED bool IsConstMethod(TCppMethod_t)
RPY_EXPORTED std::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
RPY_EXPORTED TCppIndex_t GetMethodNumArgs(TCppMethod_t)
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
RPY_EXPORTED bool IsNamespace(TCppScope_t scope)
RPY_EXPORTED TCppIndex_t GetNumDatamembers(TCppScope_t scope)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RPY_EXPORTED std::string GetMethodResultType(TCppMethod_t)
RPY_EXPORTED bool HasVirtualDestructor(TCppType_t type)
RPY_EXPORTED std::string GetMethodArgType(TCppMethod_t, TCppIndex_t iarg)
RPY_EXPORTED TCppIndex_t GetNumMethods(TCppScope_t scope)