cppyy.ll.cast 无法转换 char*

发布于 2025-01-15 21:09:11 字数 1669 浏览 0 评论 0原文

假设我们有一个来自某个外部库的名为 chr_ptr 的 char* 。

我尝试使用 cppyy.ll.cast["char*"](chr_ptr) 将此指针强制转换为 char*

预期:cppyy.LowLevelView >

实际:str

其他数据类型都可以正常工作,这个问题只发生在 char(又名 int8_t)。转换指针(比方说)int16_t 就可以了。

import cppyy
import cppyy.ll

if not hasattr(cppyy.gbl, "get_char_pointer"):
    cppyy.cppdef("""
    void* get_char_pointer()
    {
        char a = 1;
        return &a;
    }
    """)
if not hasattr(cppyy.gbl, "get_uint16_t_pointer"):
    cppyy.cppdef("""
    void* get_uint16_t_pointer()
    {
        uint16_t a = 1;
        return &a;
    }
    """)

if not hasattr(cppyy.gbl, "print_address"):
    cppyy.cppdef("""
    void print_address(void* p)
    {
        std::cout << "address is: " << p << std::endl;
    }
    """)

char_ptr = cppyy.gbl.get_char_pointer()
uint16t_ptr = cppyy.gbl.get_uint16_t_pointer()

cppyy.gbl.print_address(char_ptr)
cppyy.gbl.print_address(uint16t_ptr)

casted_char_ptr = cppyy.ll.cast["char*"](char_ptr)  # At this point expected cppyy.LowLevelView but I got str
casted_uint16t_ptr = cppyy.ll.cast["uint16_t*"](uint16t_ptr)

print()
print(type(casted_char_ptr))
print(type(casted_uint16t_ptr))

print()
try:
    cppyy.gbl.print_address(casted_char_ptr)
except TypeError as err:
    print(err)
cppyy.gbl.print_address(casted_uint16t_ptr)

结果是:

address is: 0x7fff58b64847
address is: 0x7fff58b64846

<class 'str'>
<class 'cppyy.LowLevelView'>

void ::print_address(void* p) =>
    TypeError: could not convert argument 1
address is: 0x7fff58b64846

Let's assume we have a char* named chr_ptr from some external library.

I tried to cast this pointer to char* by using cppyy.ll.cast["char*"](chr_ptr)

Expected: cppyy.LowLevelView

Actual: str

Other datatypes works well, this problem only occurs char(a.k.a. int8_t). Casting the pointer (let's say) int16_t is OK.

import cppyy
import cppyy.ll

if not hasattr(cppyy.gbl, "get_char_pointer"):
    cppyy.cppdef("""
    void* get_char_pointer()
    {
        char a = 1;
        return &a;
    }
    """)
if not hasattr(cppyy.gbl, "get_uint16_t_pointer"):
    cppyy.cppdef("""
    void* get_uint16_t_pointer()
    {
        uint16_t a = 1;
        return &a;
    }
    """)

if not hasattr(cppyy.gbl, "print_address"):
    cppyy.cppdef("""
    void print_address(void* p)
    {
        std::cout << "address is: " << p << std::endl;
    }
    """)

char_ptr = cppyy.gbl.get_char_pointer()
uint16t_ptr = cppyy.gbl.get_uint16_t_pointer()

cppyy.gbl.print_address(char_ptr)
cppyy.gbl.print_address(uint16t_ptr)

casted_char_ptr = cppyy.ll.cast["char*"](char_ptr)  # At this point expected cppyy.LowLevelView but I got str
casted_uint16t_ptr = cppyy.ll.cast["uint16_t*"](uint16t_ptr)

print()
print(type(casted_char_ptr))
print(type(casted_uint16t_ptr))

print()
try:
    cppyy.gbl.print_address(casted_char_ptr)
except TypeError as err:
    print(err)
cppyy.gbl.print_address(casted_uint16t_ptr)

The result is:

address is: 0x7fff58b64847
address is: 0x7fff58b64846

<class 'str'>
<class 'cppyy.LowLevelView'>

void ::print_address(void* p) =>
    TypeError: could not convert argument 1
address is: 0x7fff58b64846

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

若水微香 2025-01-22 21:09:12

是的,char* 是仅基于反射信息的类型之一,其预期用途并不明确。有一个半完成的补丁,允许修复函数/数据成员的 char* 的独特含义,所以即将到来,是的,cast()很明显,char* 更可能表示 byte* 而不是 C 字符串,因此应该将其作为默认值。

也就是说,在这种情况下,实际使用 std::byte* (如果您不使用 C++17,则使用 unsigned char*)应该没问题指示结果应该是什么:

casted_char_ptr = cppyy.ll.cast["std::byte*"](char_ptr) 

根据需要生成 LowLevelView

编辑:签名字节的解决方法:

cppyy.cppdef("enum signed_byte : signed char;")
casted_char_ptr = cppyy.ll.cast["signed_byte*"](char_ptr)
casted_char_ptr[0] = -1

Yes, char* is one of those types that solely based on reflection information isn't clear in its intended use. There's a half-finished patch to allow fixing up functions/data members with what their unique meaning of char* happens to be, so that's coming, and yes, cast() is a clear case where char* more likely means byte* than C-string, so should have that as default.

That said, in this case, it should be fine to actually use std::byte* (or unsigned char* if you're not using C++17) to indicate what the result should be:

casted_char_ptr = cppyy.ll.cast["std::byte*"](char_ptr) 

which produces the LowLevelView as desired.

Edit: workaround for signed byte:

cppyy.cppdef("enum signed_byte : signed char;")
casted_char_ptr = cppyy.ll.cast["signed_byte*"](char_ptr)
casted_char_ptr[0] = -1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文