Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/Converters.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2606,7 +2606,7 @@ static PyMethodDef gWrapperCacheEraserMethodDef = {
};

static void* PyFunction_AsCPointer(PyObject* pyobject,
const std::string& rettype, const std::string& signature)
const std::string& rettype, const std::string& signature, bool allowCppInstance)
{
// Convert a bound C++ function pointer or callable python object to a C-style
// function pointer. The former is direct, the latter involves a JIT-ed wrapper.
Expand Down Expand Up @@ -2653,8 +2653,11 @@ static void* PyFunction_AsCPointer(PyObject* pyobject,
return fptr;
}

if (PyCallable_Check(pyobject)) {
if (PyCallable_Check(pyobject) && (allowCppInstance || !CPPInstance_Check(pyobject))) {
// generic python callable: create a C++ wrapper function
// Sometimes we don't want to take this branch if the object is a C++
// instance, because C++ doesn't allow converting functor objects to
// function pointers, but only to std::function.
void* wpraddress = nullptr;

// re-use existing wrapper if possible
Expand Down Expand Up @@ -2759,7 +2762,7 @@ bool CPyCppyy::FunctionPointerConverter::SetArg(
}

// normal case, get a function pointer
void* fptr = PyFunction_AsCPointer(pyobject, fRetType, fSignature);
void* fptr = PyFunction_AsCPointer(pyobject, fRetType, fSignature, fAllowCppInstance);
if (fptr) {
SetLifeLine(ctxt->fPyContext, pyobject, (intptr_t)this);
para.fValue.fVoidp = fptr;
Expand Down Expand Up @@ -2791,7 +2794,7 @@ bool CPyCppyy::FunctionPointerConverter::ToMemory(
}

// normal case, get a function pointer
void* fptr = PyFunction_AsCPointer(pyobject, fRetType, fSignature);
void* fptr = PyFunction_AsCPointer(pyobject, fRetType, fSignature, fAllowCppInstance);
if (fptr) {
SetLifeLine(ctxt, pyobject, (intptr_t)address);
*((void**)address) = fptr;
Expand Down
5 changes: 4 additions & 1 deletion src/DeclareConverters.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,13 +399,16 @@ class FunctionPointerConverter : public Converter {
protected:
std::string fRetType;
std::string fSignature;
bool fAllowCppInstance = false;
};

// std::function
class StdFunctionConverter : public FunctionPointerConverter {
public:
StdFunctionConverter(Converter* cnv, const std::string& ret, const std::string& sig) :
FunctionPointerConverter(ret, sig), fConverter(cnv) {}
FunctionPointerConverter(ret, sig), fConverter(cnv) {
fAllowCppInstance = true;
}
StdFunctionConverter(const StdFunctionConverter&) = delete;
StdFunctionConverter& operator=(const StdFunctionConverter&) = delete;
virtual ~StdFunctionConverter() { delete fConverter; }
Expand Down