wlav / cppyy

Other
402 stars 41 forks source link

Checking if a wrapped object is an instance of a class template? #89

Open torokati44 opened 2 years ago

torokati44 commented 2 years ago

This is related to https://github.com/wlav/cppyy/issues/88#issuecomment-1239216367.

Is there a way for me to check whether a C++ object wrapped by Cppyy is an instance of a template class?

For example, I wish one of the last three lines here (or something similar) worked: (In the comments I show what a REPL prints after executing each line.)

import cppyy

cppyy.cppdef("#include <vector> \n std::vector<int> numbers;")
cppyy.gbl.numbers #: <cppyy.gbl.std.vector<int> object at 0x7ff596142010>

isinstance(cppyy.gbl.numbers, cppyy.gbl.std.vector[int]) #: True - BUT I need to know the type parameter

type(cppyy.gbl.numbers) #: <class cppyy.gbl.std.vector<int> at 0x55ab78329010>
type(cppyy.gbl.numbers) == cppyy.gbl.std.vector #: False
type(cppyy.gbl.numbers) == cppyy.gbl.std.vector[int] #: True - BUT I need to know the type parameter

# ??? isinstance(cppyy.gbl.numbers, cppyy.gbl.std.vector) #: TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union

# ??? isinstance(type(cppyy.gbl.numbers), cppyy.gbl.std.vector) #: TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union
# ??? isinstance(cppyy.gbl.numbers, cppyy.gbl.std.vector[*]) #: SyntaxError: invalid syntax
torokati44 commented 2 years ago

My current solution looks something like this:

def iscppinstance(obj, typestring):
    return typestring in str(type(obj))

iscppinstance(cppyy.gbl.numbers, "cppyy.gbl.std.vector") #: True

It ... is not ideal. Is there a better way?

wlav commented 2 years ago

There is no relation between the template factory object and the instantiated class. In theory, it could have been a metaclass relation, but those are needed/used already for efficient access to static variables and in that role only created on class instantiation, not beforehand, as they need to be unique for each instantiated class (in order to only have the static variables for said specific class). Ie., the template factory can't be used for that purpose, or if it were, it would still not help in this case.

A trivial solution could be to add a magic variable linking back to the original factory object? E.g. __cpp_template__ which would then be said cppyy.gbl.std.vector. Would that work?

torokati44 commented 2 years ago

A trivial solution could be to add a magic variable linking back to the original factory object? E.g. __cpp_template__ which would then be said cppyy.gbl.std.vector. Would that work?

Yes, I think that would work just fine for me!

wlav commented 1 year ago

Added in repo.

torokati44 commented 1 year ago

So, isn't this supposed to work now? :/

import cppyy

cppyy.cppdef("""
#include <vector>
std::vector<int> numbers;
""")

print(type(cppyy.gbl.numbers).__cpp_template__)
print(cppyy.gbl.numbers.__class__.__cpp_template__)
print(cppyy.gbl.numbers.__cpp_template__)

At least the first two, that is.

Or is this only for objects/classes instantiated from Python? Because the former is what I'm looking for.