如何在Python中为类类型应用SWIG OUTPUT类型映射?

发布于 2021-01-29 16:53:31

我在使用SWIG(版本3.0.6)围绕C ++库生成Python包装程序时遇到了一些麻烦。

我的问题与应用OUTPUT类型映射有关,特别是在对类类型的指针/引用的情况下。

为了说明这一点,这是我想要的标准类型,它的工作原理是:

// .h
int add(const long arg1,const long arg2,long& resultLong);

// interface.i
%apply long& OUTPUT { long& resultLong };
int add(const long arg1,const long arg2,long& resultLong);

// projectWrapper.py
def add(arg1, arg2):
    return _projectWrapper.add(arg1, arg2)
addTerm = _projectWrapper.add

// usage
>>> result = projectWrapper.add(2, 4)
>>> print result
[0, 6L]

您不必传递“ resultLong”,但会自动将其附加到结果中。大!

但是,当输出类型是指向类类型的某种指针时,这似乎不像我期望的那样工作:

// .h
int GetClassType(const char* name, exportedClassType*& resultPointer);

class exportedClassType
{...}

// interface.i
%apply exportedClassType*& OUTPUT { exportedClassType*& resultPointer };    
int GetClassType(const char* name, exportedClassType*& resultPointer);

// projectWrapper.py
def GetClassType(name, resultPointer):
    return _projectWrapper.GetClassType(name, resultPointer)
GetClassType = _projectWrapper.GetClassType

问题似乎在于SWIG并未以与简单类型相同的方式对其进行处理。它仍然在包装的函数签名中显示为“输入”参数。

// attempted usage
>>> classType = projectWrapper.GetClassType("name")
TypeError: GetClassType() takes exactly 2 arguments (1 given)

>>> result = 0
>>> projectWrapper.GetClassType("name", result)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: in method 'GetClassType', argument 2 of type 'exportedClassType *&'

有人可以告诉我我做错了什么,还是指出正确的方向吗?任何帮助表示感谢!谢谢

关注者
0
被浏览
87
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这个问题似乎已经解决了很长时间了,所以我认为我最好为这个问题提供解决方案。OUTPUT类型映射仅适用于简单类型,因此可以通过将in和类型argout映射组合来提供解决方案。

    考虑一下这种情况,我们有一个SampleImpl实现C 接口的C

    SampleBase,从技术上来说,它不是接口,因为它涉及虚拟析构函数的实现。假设我们有一个静态函数,该函数返回错误代码和接口的实现。后者是对指针的引用,这是上面的情况。

    接口头:

    // Sample.hpp
    #pragma once
    namespace Module {
      class SampleBase {
      public:
    #ifndef SWIG
        // Hint to the programmer to implement this function
        static int SampleCreate(SampleBase *&obj);
    #endif
        virtual ~SampleBase() = default;
      };
    }
    

    实施标头:

    // Sample_impl.hpp
    #pragma once
    #include "Sample.hpp"
    
    namespace Module {
      class SampleImpl : public SampleBase {
      public:
        static int SampleCreate(Module::SampleBase *&obj);
    
        SampleImpl();
        virtual ~SampleImpl();
      private:
        float a;
      };
    }
    

    实现方式:

    // Sample_impl.cpp
    #include "Sample_impl.hpp"
    #include <cstdio>
    
    namespace Module {
      int SampleImpl::SampleCreate(Module::SampleBase*& obj) {
        obj = (SampleBase*) new SampleImpl();
        return 0;
      }
      SampleImpl::SampleImpl() {
        printf("SampleImpl::SampleImpl()\n");
      }
    
      SampleImpl::~SampleImpl() {
        printf("SampleImpl::~SampleImpl()\n");
      }
    }
    

    SWIG界面(使用argout类型映射)

    // example.i
    %module example
    %{
      #define SWIG_FILE_WITH_INIT
      #include "Sample.hpp"
      #include "Sample_impl.hpp"
    %}
    
    %include "typemaps.i"
    
    %typemap(in, numinputs=0) Module::SampleBase *&obj (Module::SampleBase *temp) {
      $1 = &temp;
    }
    
    %typemap(argout) Module::SampleBase *& {
      PyObject* temp = NULL;
      if (!PyList_Check($result)) {
        temp = $result;
        $result = PyList_New(1);
        PyList_SetItem($result, 0, temp);
    
        // Create shadow object (do not use SWIG_POINTER_NEW)
        temp = SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
                 $descriptor(Module::SampleBase*),
                 SWIG_POINTER_OWN | 0);
    
        PyList_Append($result, temp);
        Py_DECREF(temp);
      }
    }
    

    在Python中的用法

    import example
    
    // Creating specialization
    obj = example.SampleImpl()
    del obj
    
    // Creation of object using output typemap
    errorCode, obj = example.SampleImpl_SampleCreate()
    del obj
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看