Skip to content

Commit

Permalink
Update CPyCppyy to use InterOp API
Browse files Browse the repository at this point in the history
This updates converter creation, templateproxy, dispatcher, cppdatamember, cppinstance and cppenum to enable parts of the API that required modifications to work with CppInterOp
  • Loading branch information
aaronj0 committed Nov 8, 2024
1 parent 01c5159 commit 7f407c6
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 43 deletions.
5 changes: 0 additions & 5 deletions src/CPPDataMember.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ static PyObject* dm_get(CPPDataMember* dm, CPPInstance* pyobj, PyObject* /* kls
}
}

// non-initialized or public data accesses through class (e.g. by help())
void* address = dm->GetAddress(pyobj);
if (!address || (intptr_t)address == -1 /* Cling error */)
return nullptr;

if (dm->fFlags & (kIsEnumPrep | kIsEnumType)) {
if (dm->fFlags & kIsEnumPrep) {
Expand Down Expand Up @@ -92,7 +88,6 @@ static PyObject* dm_get(CPPDataMember* dm, CPPInstance* pyobj, PyObject* /* kls
return pyval_from_enum(Cppyy::ResolveEnum(dm->fScope), nullptr, nullptr, dm->fScope);
}
}

// non-initialized or public data accesses through class (e.g. by help())
void* address = dm->GetAddress(pyobj);
if (!address || (intptr_t)address == -1 /* Cling error */)
Expand Down
35 changes: 19 additions & 16 deletions src/CPPEnum.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ static PyObject* pytype_from_enum_type(const std::string& enum_type)
}

//----------------------------------------------------------------------------
static PyObject* pyval_from_enum(const std::string& enum_type, PyObject* pytype,
PyObject* btype, Cppyy::TCppEnum_t etype, Cppyy::TCppIndex_t idata) {
long long llval = Cppyy::GetEnumDataValue(etype, idata);
PyObject* CPyCppyy::pyval_from_enum(const std::string& enum_type, PyObject* pytype,
PyObject* btype, Cppyy::TCppScope_t enum_constant) {
long long llval = Cppyy::GetEnumDataValue(enum_constant);

if (enum_type == "bool") {
PyObject* result = (bool)llval ? Py_True : Py_False;
Expand All @@ -38,14 +38,15 @@ static PyObject* pyval_from_enum(const std::string& enum_type, PyObject* pytype,
else
bval = PyLong_FromLongLong(llval);

if (pytype && btype) {
PyObject* args = PyTuple_New(1);
PyTuple_SET_ITEM(args, 0, bval);
PyObject* result = ((PyTypeObject*)btype)->tp_new((PyTypeObject*)pytype, args, nullptr);
bval = ((PyTypeObject*)btype)->tp_new((PyTypeObject*)pytype, args, nullptr);
Py_DECREF(args);
return result;
}
return bval;
}


//- enum methods -------------------------------------------------------------
static int enum_setattro(PyObject* /* pyclass */, PyObject* /* pyname */, PyObject* /* pyval */)
{
Expand All @@ -59,6 +60,8 @@ static PyObject* enum_repr(PyObject* self)
{
using namespace CPyCppyy;

PyObject* kls_scope = PyObject_GetAttr((PyObject*)Py_TYPE(self), PyStrings::gThisModule);
if (!kls_scope) PyErr_Clear();
PyObject* kls_cppname = PyObject_GetAttr((PyObject*)Py_TYPE(self), PyStrings::gCppName);
if (!kls_cppname) PyErr_Clear();
PyObject* obj_cppname = PyObject_GetAttr(self, PyStrings::gCppName);
Expand All @@ -67,7 +70,7 @@ static PyObject* enum_repr(PyObject* self)

PyObject* repr = nullptr;
if (kls_cppname && obj_cppname && obj_str) {
const std::string resolved = Cppyy::ResolveEnum(CPyCppyy_PyText_AsString(kls_cppname));
const std::string resolved = Cppyy::ResolveEnum(PyLong_AsVoidPtr(kls_scope));
repr = CPyCppyy_PyText_FromFormat("(%s::%s) : (%s) %s",
CPyCppyy_PyText_AsString(kls_cppname), CPyCppyy_PyText_AsString(obj_cppname),
resolved.c_str(), CPyCppyy_PyText_AsString(obj_str));
Expand Down Expand Up @@ -137,12 +140,12 @@ CPyCppyy::CPPEnum* CPyCppyy::CPPEnum_New(const std::string& name, Cppyy::TCppSco

CPPEnum* pyenum = nullptr;

const std::string& ename = scope == Cppyy::gGlobalScope ? name : Cppyy::GetScopedFinalName(scope)+"::"+name;
Cppyy::TCppEnum_t etype = Cppyy::GetEnum(scope, name);
Cppyy::TCppScope_t etype = scope;
const std::string& ename = Cppyy::GetScopedFinalName(scope);
if (etype) {
// create new enum type with labeled values in place, with a meta-class
// to make sure the enum values are read-only
const std::string& resolved = Cppyy::ResolveEnum(ename);
const std::string& resolved = Cppyy::ResolveEnum(etype);
PyObject* pyside_type = pytype_from_enum_type(resolved);
PyObject* pymetabases = PyTuple_New(1);
PyObject* btype = (PyObject*)Py_TYPE(pyside_type);
Expand All @@ -169,7 +172,7 @@ CPyCppyy::CPPEnum* CPyCppyy::CPPEnum_New(const std::string& name, Cppyy::TCppSco
PyObject* pyresolved = CPyCppyy_PyText_FromString(resolved.c_str());
PyDict_SetItem(dct, PyStrings::gUnderlying, pyresolved);
Py_DECREF(pyresolved);

// add the __module__ to allow pickling
std::string modname = TypeManip::extract_namespace(ename);
TypeManip::cppscope_to_pyscope(modname); // :: -> .
Expand All @@ -191,10 +194,10 @@ CPyCppyy::CPPEnum* CPyCppyy::CPPEnum_New(const std::string& name, Cppyy::TCppSco
((PyTypeObject*)pyenum)->tp_str = ((PyTypeObject*)pyside_type)->tp_repr;

// collect the enum values
Cppyy::TCppIndex_t ndata = Cppyy::GetNumEnumData(etype);
for (Cppyy::TCppIndex_t idata = 0; idata < ndata; ++idata) {
PyObject* val = pyval_from_enum(resolved, pyenum, pyside_type, etype, idata);
PyObject* pydname = CPyCppyy_PyText_FromString(Cppyy::GetEnumDataName(etype, idata).c_str());
std::vector<Cppyy::TCppScope_t> econstants = Cppyy::GetEnumConstants(etype);
for (auto *econstant : econstants) {
PyObject* val = pyval_from_enum(resolved, pyenum, pyside_type, econstant);
PyObject* pydname = CPyCppyy_PyText_FromString(Cppyy::GetFinalName(econstant).c_str());
PyObject_SetAttr(pyenum, pydname, val);
PyObject_SetAttr(val, PyStrings::gCppName, pydname);
Py_DECREF(pydname);
Expand All @@ -215,4 +218,4 @@ CPyCppyy::CPPEnum* CPyCppyy::CPPEnum_New(const std::string& name, Cppyy::TCppSco
}

return pyenum;
}
}
6 changes: 0 additions & 6 deletions src/CPPInstance.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,6 @@ static PyObject* op_item(CPPInstance* self, Py_ssize_t idx)
return nullptr;
}

Py_ssize_t idx = PyInt_AsSsize_t(pyidx);
if (idx == (Py_ssize_t)-1 && PyErr_Occurred())
return nullptr;

if (idx < 0) {
// this is debatable, and probably should not care, but the use case is pretty
// circumscribed anyway, so might as well keep the functionality simple
Expand Down Expand Up @@ -413,8 +409,6 @@ static PyMethodDef op_methods[] = {
(char*)"dispatch to selected overload"},
{(char*)"__smartptr__", (PyCFunction)op_get_smartptr, METH_NOARGS,
(char*)"get associated smart pointer, if any"},
{(char*)"__getitem__", (PyCFunction)op_getitem, METH_O,
(char*)"pointer dereferencing"},
{(char*)"__reshape__", (PyCFunction)op_reshape, METH_O,
(char*)"cast pointer to 1D array type"},
{(char*)nullptr, nullptr, 0, nullptr}
Expand Down
3 changes: 1 addition & 2 deletions src/Converters.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3370,8 +3370,7 @@ CPyCppyy::Converter* CPyCppyy::CreateConverter(Cppyy::TCppType_t type, cdims_t d
} else
cnv = CreateConverter(value_type);
if (cnv || use_byte_cnv)
return new InitializerListConverter(Cppyy::GetScopeFromType(realType),
CreateConverter(value_type), cnv, Cppyy::SizeOf(value_type));
return new InitializerListConverter(Cppyy::GetScopeFromType(realType), value_type);
}

//-- still nothing? use a generalized converter
Expand Down
14 changes: 7 additions & 7 deletions src/Dispatcher.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,11 @@ namespace {
using namespace Cppyy;

static inline
std::vector<TCppIndex_t> FindBaseMethod(TCppScope_t tbase, const std::string mtCppName)
std::vector<TCppMethod_t> FindBaseMethod(TCppScope_t tbase, const std::string mtCppName)
{
// Recursively walk the inheritance tree to find the overloads of the named method
std::vector<TCppIndex_t> result;
result = GetMethodIndicesFromName(tbase, mtCppName);
std::vector<TCppMethod_t> result;
result = GetMethodsFromName(tbase, mtCppName);
if (result.empty()) {
for (TCppIndex_t ibase = 0; ibase < GetNumBases(tbase); ++ibase) {
TCppScope_t b = GetScope(GetBaseName(tbase, ibase));
Expand Down Expand Up @@ -366,10 +366,10 @@ bool CPyCppyy::InsertDispatcher(CPPScope* klass, PyObject* bases, PyObject* dct,
// TODO: should probably invert this looping; but that makes handling overloads clunky
PyObject* key = PyList_GET_ITEM(keys, i);
std::string mtCppName = CPyCppyy_PyText_AsString(key);
const auto& v = FindBaseMethod(tbase, mtCppName);
for (auto idx : v)
InjectMethod(Cppyy::GetMethod(tbase, idx), mtCppName, code);
if (!v.empty()) {
const auto& methods = FindBaseMethod(tbase, mtCppName);
for (auto method : methods)
InjectMethod(method, mtCppName, code);
if (!methods.empty()) {
if (PyDict_DelItem(clbs, key) != 0) PyErr_Clear();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Pythonize.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -568,9 +568,9 @@ static PyObject* vector_iter(PyObject* v) {
if (!vi->vi_klass) {
// look for a special case of pointer to a class type (which is a builtin, but it
// is more useful to treat it polymorphically by allowing auto-downcasts)
const std::string& clean_type = TypeManip::clean_type(value_type, false, false);
const std::string& clean_type = TypeManip::clean_type(Cppyy::GetTypeAsString(value_type), false, false);
Cppyy::TCppScope_t c = Cppyy::GetScope(clean_type);
if (c && TypeManip::compound(value_type) == "*") {
if (c && TypeManip::compound(Cppyy::GetTypeAsString(value_type)) == "*") {
vi->vi_klass = c;
vi->vi_flags = vectoriterobject::kIsPolymorphic;
}
Expand Down
5 changes: 0 additions & 5 deletions src/TemplateProxy.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -856,11 +856,6 @@ static PyObject* tpp_overload(TemplateProxy* pytmpl, PyObject* args)
PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
PyErr_Fetch(&pytype, &pyvalue, &pytrace);

std::string proto = Utility::ConstructTemplateArgs(nullptr, args);
Cppyy::TCppScope_t scope = ((CPPClass*)pytmpl->fTI->fPyClass)->fCppType;
Cppyy::TCppMethod_t cppmeth = Cppyy::GetMethodTemplate(
scope, pytmpl->fTI->fCppName, proto.substr(1, proto.size()-2));

if (!cppmeth) {
PyErr_Restore(pytype, pyvalue, pytrace);
return nullptr;
Expand Down

0 comments on commit 7f407c6

Please sign in to comment.