【问题标题】:Dealing with in/out string parameters in Swig Python在 Swig Python 中处理输入/输出字符串参数
【发布时间】:2021-12-28 16:12:08
【问题描述】:

也许有人知道,如何重写 getVersion 以获取 Python versionlegacyVersion 作为函数的结果,而不是将它们传递为 输入/输出参数

   class DeviceInterface {
   public:
      virtual uint32_t getVersion(uint8_t* version, uint8_t* legacyVersion ) = 0;
   };

现在我在 SWIG 接口文件中创建了额外的函数,但当前的实现只返回一个参数而不是两个。

%ignore DeviceInterface::getVersion( uint8_t* version, uint8_t* legacyVersion );

%extend DeviceInterface {
    virtual char * getVersion() {
        static uint8_t _v[200];
        static uint8_t _lv[200];
        $self->getVersion(_v, _lv);
        return (char *)_lv;
    }
};

更新

现在我使用 @ignore@extend 功能。但我想还有更优雅的方式。这是我的工作 SWIG 界面 sn-p:

%extend DeviceInterface {
    virtual PyObject *getVersion() {
        static uint8_t _v[200];
        static uint8_t _lv[200];
        uint32_t libCode = $self->getVersion(_v, _lv);
        return Py_BuildValue("(l,s,s)", libCode, (char *)_v, (char *)_lv);
    }
};

【问题讨论】:

    标签: python c++ pointers swig


    【解决方案1】:

    您可以定义自己的类型映射来处理输出参数。在这种情况下,类型映射将 all uint32_t* 参数视为 200 字节的输出缓冲区。这是一个没有错误检查的最小示例。

    %module test
    
    %include <stdint.i>
    
    // Require no input parameter.  Just allocate a fixed-sized buffer.
    %typemap(in,numinputs=0) uint8_t* %{
        $1 = new uint8_t[200];
    %}
    
    // Free the temporary buffer when done converting the argument
    %typemap(freearg) uint8_t* %{
        delete [] $1;
    %}
    
    // On output, convert the buffer to a Python byte string
    %typemap(argout) uint8_t* %{
        $result = SWIG_Python_AppendOutput($result, PyBytes_FromString(reinterpret_cast<char*>($1)));
    %}
    
    // Example implementation
    %inline %{
    #include <stdint.h>
    class DeviceInterface {
    public:
        virtual uint32_t getVersion(uint8_t* version, uint8_t* legacyVersion ) {
            strcpy(reinterpret_cast<char*>(version),"1.0.0");
            strcpy(reinterpret_cast<char*>(legacyVersion),"2.0.0");
            return 0;
        }
    };
    %}
    

    输出:

    >>> import test
    >>> d=test.DeviceInterface()
    >>> d.getVersion()
    [0, b'1.0.0', b'2.0.0']
    

    注意输出是返回值和两个输出参数的串联。

    【讨论】:

    • 感谢您的详细解答。我可以采用相同的方式,但使用 C++ 结构的输出数组,例如uint32_t getJobs(Jobs *array, uint8_t &amp;jobsCount) 其中 struct Job 有几个原始类型字段和 uint8_t 字节缓冲区。如果是,我应该使用什么 API 而不是 PyBytes_FromString 来修补结构。
    • 还有一个问题。与您的相比,我的实现有什么缺点吗?
    • @Den 带有类型映射,它会自动应用于带有 uint32_t* 参数的任何函数,但可以通过命名参数和 %apply 进行限制。您的方法必须单独忽略和扩展每个功能。对于您的其他问题,答案是肯定的,但要问一个新的 SO 问题以获取代码示例答案。
    • here is it :) 非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多