Skip to content
Merged
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
12 changes: 9 additions & 3 deletions src/Converters.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,12 @@ static void* PyFunction_AsCPointer(PyObject* pyobject,
// function pointer. The former is direct, the latter involves a JIT-ed wrapper.
static PyObject* sWrapperCacheEraser = PyCFunction_New(&gWrapperCacheEraserMethodDef, nullptr);

// FIXME: avoid string comparisons and parsing
std::string true_signature = signature;
true_signature.erase(std::remove(true_signature.begin(), true_signature.end(), ' '), true_signature.end());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give an example what's the type of things new get and we should edit out?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize we should probably move forward with this PR. We could probably do a better job at the converter comparison level but that's probably good enough to make progress...

if (true_signature.rfind("(void)") != std::string::npos)
true_signature = true_signature.substr(0, true_signature.size() - 6) + "()";

using namespace CPyCppyy;

if (CPPOverload_Check(pyobject)) {
Expand Down Expand Up @@ -2637,7 +2643,7 @@ static void* PyFunction_AsCPointer(PyObject* pyobject,
if (pytmpl->fTemplateArgs)
fullname += CPyCppyy_PyText_AsString(pytmpl->fTemplateArgs);
Cppyy::TCppScope_t scope = ((CPPClass*)pytmpl->fTI->fPyClass)->fCppType;
Cppyy::TCppMethod_t cppmeth = Cppyy::GetMethodTemplate(scope, fullname, signature);
Cppyy::TCppMethod_t cppmeth = Cppyy::GetMethodTemplate(scope, fullname, true_signature);
if (cppmeth) {
void* fptr = (void*)Cppyy::GetFunctionAddress(cppmeth, false);
if (fptr) return fptr;
Expand All @@ -2650,7 +2656,7 @@ static void* PyFunction_AsCPointer(PyObject* pyobject,
void* wpraddress = nullptr;

// re-use existing wrapper if possible
auto key = rettype+signature;
auto key = rettype+true_signature;
const auto& lookup = sWrapperLookup.find(key);
if (lookup != sWrapperLookup.end()) {
const auto& existing = lookup->second.find(pyobject);
Expand Down Expand Up @@ -2678,7 +2684,7 @@ static void* PyFunction_AsCPointer(PyObject* pyobject,
return nullptr;

// extract argument types
const std::vector<std::string>& argtypes = TypeManip::extract_arg_types(signature);
const std::vector<std::string>& argtypes = TypeManip::extract_arg_types(true_signature);
int nArgs = (int)argtypes.size();

// wrapper name
Expand Down
2 changes: 2 additions & 0 deletions src/Cppyy.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ namespace Cppyy {
CPPYY_IMPORT
bool IsClassType(TCppType_t type);
CPPYY_IMPORT
bool IsFunctionPointerType(TCppType_t type);
CPPYY_IMPORT
TCppType_t GetType(const std::string& name, bool enable_slow_lookup = false);
CPPYY_IMPORT
bool AppendTypesSlow(const std::string &name,
Expand Down
21 changes: 18 additions & 3 deletions src/Executors.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,13 @@ CPyCppyy::Executor* CPyCppyy::CreateExecutor(Cppyy::TCppType_t type, cdims_t dim

// resolve typedefs etc.
Cppyy::TCppType_t resolvedType = Cppyy::ResolveType(type);
const std::string& resolvedTypeStr = Cppyy::GetTypeAsString(resolvedType);
// FIXME: avoid string comparisons and parsing
std::string resolvedTypeStr = Cppyy::GetTypeAsString(resolvedType);
if (Cppyy::IsFunctionPointerType(resolvedType)) {
resolvedTypeStr.erase(std::remove(resolvedTypeStr.begin(), resolvedTypeStr.end(), ' '), resolvedTypeStr.end());
if (resolvedTypeStr.rfind("(void)") != std::string::npos)
resolvedTypeStr = resolvedTypeStr.substr(0, resolvedTypeStr.size() - 6) + "()";
}

// a full, qualified matching executor is preferred
if (resolvedTypeStr != fullType) {
Expand All @@ -924,8 +930,8 @@ CPyCppyy::Executor* CPyCppyy::CreateExecutor(Cppyy::TCppType_t type, cdims_t dim
//-- nothing? ok, collect information about the type and possible qualifiers/decorators
bool isConst = strncmp(resolvedTypeStr.c_str(), "const", 5) == 0;
const std::string& cpd = TypeManip::compound(resolvedTypeStr);
Cppyy::TCppType_t realType = Cppyy::GetRealType(resolvedType);
std::string realTypeStr = Cppyy::GetTypeAsString(realType);
Cppyy::TCppType_t realType = Cppyy::IsFunctionPointerType(resolvedType) ? resolvedType : Cppyy::GetRealType(resolvedType);
std::string realTypeStr = Cppyy::IsFunctionPointerType(resolvedType) ? resolvedTypeStr : Cppyy::GetTypeAsString(realType);
const std::string compounded = cpd.empty() ? realTypeStr : realTypeStr + cpd;

// accept unqualified type (as python does not know about qualifiers)
Expand Down Expand Up @@ -981,6 +987,15 @@ CPyCppyy::Executor* CPyCppyy::CreateExecutor(Cppyy::TCppType_t type, cdims_t dim
result = new InstancePtrRefExecutor(klass);
} else
result = new InstancePtrExecutor(klass);
} else if (realTypeStr.find("(*)") != std::string::npos ||
(realTypeStr.find("::*)") != std::string::npos)) {
// this is a function pointer
// TODO: find better way of finding the type
auto pos1 = realTypeStr.find('(');
auto pos2 = realTypeStr.find("*)");
auto pos3 = realTypeStr.rfind(')');
result = new FunctionPointerExecutor(
realTypeStr.substr(0, pos1), realTypeStr.substr(pos2+2, pos3-pos2-1));
} else {
// unknown: void* may work ("user knows best"), void will fail on use of return value
h = (cpd == "") ? gExecFactories.find("void") : gExecFactories.find("void ptr");
Expand Down
4 changes: 2 additions & 2 deletions src/Utility.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ void CPyCppyy::Utility::ConstructCallbackPreamble(const std::string& retType,
int nArgs = (int)argtypes.size();

// return value and argument type converters
bool isVoid = retType == "void";
bool isVoid = retType.find("void") == 0; // might contain trailing space
if (!isVoid)
code << " CPYCPPYY_STATIC std::unique_ptr<CPyCppyy::Converter, std::function<void(CPyCppyy::Converter*)>> "
"retconv{CPyCppyy::CreateConverter(\""
Expand Down Expand Up @@ -931,7 +931,7 @@ void CPyCppyy::Utility::ConstructCallbackPreamble(const std::string& retType,
void CPyCppyy::Utility::ConstructCallbackReturn(const std::string& retType, int nArgs, std::ostringstream& code)
{
// Generate code for return value conversion and error handling.
bool isVoid = retType == "void";
bool isVoid = retType.find("void") == 0; // might contain trailing space
bool isPtr = Cppyy::ResolveName(retType).back() == '*';

if (nArgs)
Expand Down
Loading