Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScopeProxy doesn't update when c++ symbol updates #10

Open
wrongbad opened this issue Jan 13, 2024 · 3 comments
Open

ScopeProxy doesn't update when c++ symbol updates #10

wrongbad opened this issue Jan 13, 2024 · 3 comments

Comments

@wrongbad
Copy link

wrongbad commented Jan 13, 2024

Here's a complete reproducible example:

>>> import cppyy
>>> cppyy.include("iostream")
True
>>> cppyy.cppexec("int x = 1; std::cout << x << std::endl;")
1
True
>>> cppyy.gbl.x
1
>>> cppyy.cppexec("int x = 2; std::cout << x << std::endl;")
2
True
>>> cppyy.gbl.x
1
>>> del cppyy.gbl.x
>>> cppyy.cppexec("int x = 3; std::cout << x << std::endl;")
3
True
>>> cppyy.gbl.x
3

I would expect the 2nd eval of cppyy.gbl.x to return 2 but it seems to have cached the value 1 until I explicitly delete the cached value.

@wlav
Copy link
Owner

wlav commented Jan 16, 2024

Yes, on the Cling side, the redeclaration simply masks the first declaration. Ie., there are 2 global variables named x in the system; it's not an update of the original variable. Since lookups are expensive and there is no callback from Cling to indicate that a variable has been redeclared, there's no easy way to propagate such an update other than forcing a fresh lookup by using an explicit del.

Note that the same is true in Cling:

>>> import cppyy
>>> cppyy.cppexec("int x = 1;")
True
>>> cppyy.cppdef("int f() { return x; }")
True
>>> cppyy.gbl.f()
1
>>> cppyy.cppexec("int x = 2;")
True
>>> cppyy.gbl.f()
1
>>> cppyy.cppdef("int g() { return x; }")
True
>>> cppyy.gbl.g()
2
>>> 

Again, this is because a redeclaration isn't a replacement.

@wrongbad
Copy link
Author

I see. Thanks for the explanation.

And to be clear, you mean symbol lookups are slow, but looking up new values at the same address is fine to do each time right?

@wlav
Copy link
Owner

wlav commented Jan 16, 2024

Yes. Lookups are slow b/c on the Python side, all that is known is that name x, not what it is and thus where to find it. I.e., there's a whole range of lookups happening (is this a class? a function? an enum? a ...). Furthermore, the following is also legal in Cling:

>>> import cppyy
>>> cppyy.cppexec("int x = 1;")
True
>>> cppyy.gbl.x
1
>>> del cppyy.gbl.x
>>> cppyy.cppexec('class x {};')
True
>>> cppyy.gbl.x
<class cppyy.gbl.x at 0x149704dc0>
>>> 

Thus storing "x is a global variable of type int", although sufficient for the example above, is also not a general solution. I.e., an actual complete solution would require a complete lookup on every use, which will give a couple orders of magnitude performance reduction in regular use. (Note that erasing a class doesn't work the same as erasing an int global variable, so the opposite case doesn't actually work.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants