wlav / cppyy

Other
384 stars 38 forks source link

Setting any member from Python for a C++ class #222

Closed jmcarcell closed 3 months ago

jmcarcell commented 3 months ago

This code (cppyy 3.1.2) will set a member that doesn't exist and silently not say anything. This could be a problem when it's actually a typo instead of the actual member and the intended member is not being set. Is there a way of enforcing that only existing C++ members can be set?

import cppyy
cppyy.cppdef("""
class A {
public:
int a;
float b;
};
""")
a = cppyy.gbl.A()
a.z = 3
print(a.z)
wlav commented 3 months ago

This is normal Python behavior:

class A:
    def __init__(self):
        self.a = 0
        self.b = 0.

a = A()
a.z = 3
print(a.z)

One way would be to not have a __dict__ attribute, but that's fundamental to the inner workings (it's also useful for adding methods, which is common in pythonizations).

Alternatively, you can add a filter, installed through a pythonization:

def Asetattr(self, attr, val):
    if not attr in type(self).__dict__:
        raise AttributeError(attr)

cppyy.gbl.A.__setattr__ = Asetattr

but that only works for simple structs (the above code does not search for base class members, although you can probably extend it to search the mro).

Again, though, this is normal behavior and an occasional typo should be a non-issue: it's the nature of all Python code that it needs to be tested.