使用 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) 将产生 &lt;cppyy.LowLevelView object at 0x7fe1eb0b31b0&gt;。现在,要将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* 字符串的主要内容,如果未能解决你的问题,请参考以下文章

cppyy - 如何调用接受集合的 c++ 函数?

使用cppyy时如何在python中创建子类?

从 c++ 中用 cppyy 读取 char16_t* 字符串

在 python 中使用 cppyy 时,指针变量引发错误为未知类型

通过 C++ pythonization 回调将 operator() 的 cppyy 自动映射恢复到 __getitem__

如何使用 cppyy 从指针索引类数组