首页 > 解决方案 > 使用 c++ 中的 cppyy 在用户定义的结构中读取 char16_t* 字符串

问题描述

根据这个问题: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 能够处理刺痛,但我不知道如何交出数组并包装字符串。

(工作)香草 ctypes 代码:

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 更高版本中的问题..

标签: pythoncppyy

解决方案


尽管我仍然不清楚这里的实际意图,尤其是。由于没有可运行的示例,我猜它的要点是数组类型被视为“数据”而不是“字符串”,并且您希望这种解释相反。

让我们从可运行的东西开始:

import cppyy

cppyy.cppdef(r"""\
  struct AxisInformation {
  AxisInformation() : name{u'h', u'e', u'l', u'l', u'o', u'\0'} {}
  char16_t name[16];
};""")

ai = cppyy.gbl.AxisInformation()

此时,ai.name是一个数组类型,所以 egprint(ai.name)将 yield <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-随意的


推荐阅读