【问题标题】:Custom SWIG accessor functions or struct member type cast自定义 SWIG 访问器函数或结构成员类型转换
【发布时间】:2022-01-05 15:57:59
【问题描述】:

我需要一些方法将 unit8_t 数组转换为 char 数组或 char * 字符串,以在 Python 端创建 Job 对象并打印它在从 C++ 端获取对象后字段。 SWIG 是否支持自定义访问器函数(即 get/set)或“魔术”arg 转换?

我尝试了 @ignore 功能来跳过 identifiername 成员的处理并添加 %inline 访问器功能,但no result.

在 Python 中:

job = someFuncInCppCode()
print("Identifier: " + job.identifier)

调用 Python 打印时出错:

Execution error: can only concatenate str (not "SwigPyObject") to str

C++ 头文件

struct Job
{
  static const int MaxIdentifierLength = 20;
  static const int MaxNameLength = 40;

  uint8_t  identifier[MaxIdentifierLength];
  uint8_t   name[MaxNameLength];
  uint32_t  status;
};

SWIG 自动生成的代码:

SWIGINTERN PyObject *_wrap_Job_identifier_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
    PyObject *resultobj = 0;
    Job *arg1 = (Job *) 0 ;
    void *argp1 = 0 ;
    int res1 = 0 ;
    PyObject *swig_obj[1] ;
    uint8_t *result = 0 ;

    if (!args) SWIG_fail;
    swig_obj[0] = args;
    res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Xrite__Device_Cpp__Topaz__Job, 0 |  0 );
    if (!SWIG_IsOK(res1)) {
        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Job_identifier_get" "', argument " "1"" of type '" "Job *""'"); 
    }
    arg1 = reinterpret_cast<Job * >(argp1);
    result = (uint8_t *)(uint8_t *) ((arg1)->identifier);
    resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_unsigned_char, 0 |  0 );
    return resultobj;
    fail:
    return NULL;
}

【问题讨论】:

    标签: python string struct char swig


    【解决方案1】:

    一种方法是为该数组类型定义一个输出类型映射。请参阅SWIG documentation 中的Typemaps for arrays。示例:

    test.i

    %module test
    
    %include <stdint.i>
    
    // Convert uint8_t array assumed to be a null-terminated string.
    %typemap(out) uint8_t[ANY] %{
        $result = PyBytes_FromString(reinterpret_cast<char*>($1));
    %}
    
    %inline %{
    #include <stdint.h>
    
    struct Job
    {
      static const int MaxIdentifierLength = 20;
      static const int MaxNameLength = 40;
    
      uint8_t  identifier[MaxIdentifierLength];
      uint8_t  name[MaxNameLength];
      uint32_t status;
    };
    
    // test function
    Job func() {
        return {"hello","world",5};
    }
    %}
    

    演示:

    >>> import test
    >>> j=test.func()
    >>> j.name
    b'world'
    >>> j.identifier
    b'hello'
    >>> j.status
    5
    

    如果您希望数组中的每个字节都可见,请改用此类型映射:

    %typemap(out) uint8_t[ANY] %{
        $result = PyBytes_FromStringAndSize(reinterpret_cast<char*>($1), $1_dim0);
    %}
    

    演示:

    >>> import test
    >>> j=test.func()
    >>> j.identifier
    b'hello\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
    

    【讨论】:

    • 我只是将 PyBytes_FromString 替换为 PyString_FromString 和 @MarkTolonen 的映射就像一个魅力。
    • 你能看看2d array issue吗?谢谢
    • PyString 来自 Python 2。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2023-03-05
    • 1970-01-01
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多