Closed fabbbbbbbb closed 1 year ago
Although uint8_t
is normally implemented as an unsigned char
, it's intend is to be an 8bit integer type. In Python, you can't really mix them the way you can in C as there is no char
type, only str
(or bytes
) of length 1, so this is mainly a convention for the most common use case. However, Cling isn't consistent in keeping uint8_t
as a type such that it can be mapped to a Python int
and will in some cases serve up unsigned char
, but even worse in this case, where it is translated into an Int_t
(an internal typedef).
Thank you for the analysis!
In the end, what do you think is the best way to fix this problem?
As a user, my point of view is that in v2.3, it's a bit awkward to use uint8_t
, because you have to use ord(x)
every time you want to compare it to an int.
But at least it worked, so I wouldn't complain if it was simply reverted to the previous behavior.
This one is fixed in repo, as well as several other cases that I tried to cover. There are still more, though, e.g. when using int8_t
or uint8_t
as template arguments.
Thank you for the quick fix. I can confirm that this bug is fixed.
I just noted one thing though:
if in the struct, I use an alias to uint8_t (for instance, typedef uint8_t UBYTE; struct T { UBYTE a; };
), then t.a
is an str
as in cppyy2.3.
Not a big deal, I can just keep the ord(t.a)
in this case, but it's slightly inconsistent.
Anyway, I'll close this bug since it is solved.
Yes, that case is even harder: the only types the mapping code deals with are the one that is actually used (UBYTE
in this case) and the canonical (unsigned char
here). Obviously, Cling can figure out that there's an intermediate uint8_t
type, but that's just another corner to fill (as said, there are still several I know of ... it's a complex one).
This being Python, you can bake in a workaround, or create a pythonization:
import cppyy
cppyy.cppdef("""\
typedef uint8_t UBYTE; struct T { UBYTE a; };
""")
cppyy.cppdef("""\
uint8_t T_get_a(T* t) {
return t->a;
}""")
print("PRE:", type(cppyy.gbl.T().a))
cppyy.gbl.T.a = property(cppyy.gbl.T_get_a)
print("POST:", type(cppyy.gbl.T().a))
With cppyy 2.3.1 and python3.8, I could do the following:
With cppyy 2.4.0 and above, I get a sigsev:
When I simply want to print t.t[0] I get a random number above 255. Trying to set it has no effect.
I've tried by installing from pip and from sources, and with both python 3.8 and 3.11.
Interestingly enough, if I use "unsigned char" instead of "uint8_t", it works as expected; however I have plenty of uint8_t in my code, so it's not an option.
cppyy-2.4.0 changelog mentions something about uint8_t enums, that were previously treated as 1-character strings, so it seems that uin8t_t are now incorrectly handled.
Note: may be related to issue 154, but different since it crashes python, and I don't get the correct values even if I try to cast s.t as an "unsigned char*"