使用 c++ 中的 cppyy 在用户定义的结构中读取 char16_t* 字符串
Posted
技术标签:
【中文标题】使用 c++ 中的 cppyy 在用户定义的结构中读取 char16_t* 字符串【英文标题】:Read char16_t* String in user defined struct with cppyy from c++ 【发布时间】:2021-08-09 10:16:33 【问题描述】:根据这个问题:Read char16_t* String with cppyy from c++ 我对用户定义的结构中的 char16_t* 有一个新问题。
给定一个 C++ 函数:
MLPI_API MLPIRESULT mlpiMotionGetConfiguredAxes(const MLPIHANDLE connection, MlpiAxisInformation* configAxes, const ULONG numElements, ULONG *numElementsRet);
typedef unsigned int ULONG;
typedef char16_t WCHAR16;
typedef struct MlpiAxisInformation
MlpiAxisRef axis; //!< Logical axis address.
ULONG deviceAddress; //!< (SERCOS) device address.
MlpiAxisType axisType; //!< Type of axis (virtual, real, etc...).
WCHAR16 name[MLPI_MOTION_MAX_AXIS_NAME_LEN]; //!< The axis name.
MlpiAxisInformation;
对于 ctypes,我将结构定义为类并从中构建了一个数组。但随后字符串不起作用。 Cppyy 能够处理刺痛,但我不知道如何交出数组并包装字符串..
(工作)Vanilla ctypes-code:
class MlpiAxisRef(ctypes.Structure):
_fields_ = [
("controlNo",ctypes.c_int),
("axisNo",ctypes.c_int)]
class MlpiAxisInformation(ctypes.Structure):
_fields_ = [
("axis", MlpiAxisRef),
("deviceAddress",ctypes.c_ulong),
("axisType", ctypes.c_int),
("name", ctypes.c_wchar*100)
]
def MLPIGetConfiguredAxes(self) -> List[MlpiAxisInformation]:
length = ctypes.c_ulong(99)
length_ret = ctypes.c_ulong(0)
self._mlpi.mlpiMotionGetConfiguredAxes.argtypes = (ctypes.c_ulonglong, ctypes.POINTER(MlpiAxisInformation), ctypes.c_ulong, ctypes.POINTER(ctypes.c_ulong))
self._mlpi.mlpiMotionGetConfiguredAxes.restype = ctypes.c_long
val = (MlpiAxisInformation*100)()
ret = self._mlpi.mlpiMotionGetConfiguredAxes(self.con, val, length, length_ret)
如何用工作字符串取回 MlpiAxisInformation-Array?
cppyy = "==1.7.0" 由于 dockerize 更高版本的问题..
【问题讨论】:
(旁白:dockerize 的问题是什么?2.0.0 引入了更新的 Clang9,所以这是一个相当大的升级。)否则,我试图弄清楚你到底在问什么,因为那里不是一个可运行的示例 AFACIT 吗?char16_t
的固定大小的数组被 cppyy 视为一个数组,而不是一个字符串。问题是如何将这样的数组转换为 unicode Python str
?
嗨,Wim,没有可运行的示例,因为它正在使用硬件设备。而且我无法访问库的代码(只是标题),所以我无法编写模拟器。您在链接问题中完美解决了 char16_t 的问题,但我不知道如何将自定义结构数组作为指针参数解决。 dockerize问题是2.0.0之前的问题,也许我会重试。我稍后会报告。
【参考方案1】:
虽然我仍然不清楚这里的实际意图,尤其是。由于没有可运行的示例,我猜它的要点是数组类型被视为“数据”而不是“字符串”,并且您希望颠倒这种解释。
让我们从可运行的东西开始:
import cppyy
cppyy.cppdef(r"""\
struct AxisInformation
AxisInformation() : nameu'h', u'e', u'l', u'l', u'o', u'\0'
char16_t name[16];
;""")
ai = cppyy.gbl.AxisInformation()
此时,ai.name
是一个数组类型,例如print(ai.name)
将产生 <cppyy.LowLevelView object at 0x7fe1eb0b31b0>
。现在,要将char16_t[]
视为字符串,它应该是char16_t
。到达那里的一种方法是投射它:
import cppyy.ll
name = cppyy.ll.cast['char16_t*'](ai.name)
当打印时,现在产生hello
。
这就是你所追求的吗?
请注意,有一个开放的错误报告和建议的解决方案,用于注释这些 char 数组应该表示的内容,因为 C++ 的一个普遍问题是“数据”通常表示为某种字符类型,因为这些很容易与指针算法一起使用(因此自动转换必须猜测最可能的用途;这里是错误的):https://bitbucket.org/wlav/cppyy/issues/344/failed-to-handle-char-array-with-arbitrary
【讨论】:
您可以将讨论转移到 github 问题并在此处发布最终答案吗?不是在这里讨论的最佳平台.. 当然;我很好。以上是关于使用 c++ 中的 cppyy 在用户定义的结构中读取 char16_t* 字符串的主要内容,如果未能解决你的问题,请参考以下文章
从 c++ 中用 cppyy 读取 char16_t* 字符串
在 python 中使用 cppyy 时,指针变量引发错误为未知类型
通过 C++ pythonization 回调将 operator() 的 cppyy 自动映射恢复到 __getitem__