cppyy icon indicating copy to clipboard operation
cppyy copied to clipboard

can not convert null function pointer

Open N-Coder opened this issue 2 years ago • 2 comments

Cppyy fails with an exception if one tries to access a function pointer that is null:

>>> cppyy.cppdef("using FT = void(*)(); FT func = nullptr;")
True
>>> cppyy.gbl.FT
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: <namespace cppyy.gbl at 0x556b0ec2a060> has no attribute 'FT'. Full details:
  type object '' has no attribute 'FT'
  'FT' is not a known C++ class
  'FT' is not a known C++ template
  'FT' is not a known C++ enum
>>> cppyy.gbl.func
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: <namespace cppyy.gbl at 0x556b0ec2a060> has no attribute 'func'. Full details:
  type object '' has no attribute 'func'
  'func' is not a known C++ class
  can not convert null function pointer

I would probably expect cppyy.bind_object(cppyy.nullptr, cppyy.gbl.FT) as return value, but it's also not clear to me why the FT typedef cannot be accessed.

N-Coder avatar Dec 29 '22 18:12 N-Coder

Issue is that a function pointer isn't represented as a function pointer b/c Cling doesn't track it as a Type but as a FunctionDecl. I've never dug into it to see whether that's for Clang reasons or just a Cling artifact. The upshot is that the chosen representation of a function pointer is an std::function<> using a JITed helper function, so that the actual function type isn't needed.

That in turn makes the "pointer" an object, which is automatically callable using existing machinery. And yes, I could simply expose that when null, but it wouldn't be cppyy.bind_object(cppyy.nullptr, cppyy.gbl.FT) (for the reason explained above), but rather a callable that evaluates to False and raises std::bad_function_call on use. I'll make that change if it doesn't break anything.

In addition to Cling not giving me the type of FT, exposing FT as a type would require it to be a custom Python type as there's nothing equivalent in Python that would do. Using std::function wouldn't work b/c that doesn't have pointer behavior. The only reason I could see for doing that is for templates (same as was done for enums).

wlav avatar Jan 03 '23 23:01 wlav

Changed in repo: a nullptr return now gives an std::function object that is uncallable and evaluates to False.

wlav avatar Jan 04 '23 02:01 wlav