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

SWi*_*ams 10 c++ python swig

我在使用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]
Run Code Online (Sandbox Code Playgroud)

您不必传入"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
Run Code Online (Sandbox Code Playgroud)

问题似乎是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 *&'
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我我做错了什么或指出我正确的方向?任何帮助感激不尽!谢谢

Jen*_*unk 3

这个问题似乎已经有很长一段时间没有解决了,所以我想我最好为这个问题提供一个解决方案。OUTPUT类型映射仅适用于简单类型,因此通过组合aninargout类型映射给出了解决方案。

考虑一下这种情况,我们有一个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;
  };
}
Run Code Online (Sandbox Code Playgroud)

实现头:

// 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;
  };
}
Run Code Online (Sandbox Code Playgroud)

执行:

// 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");
  }
}
Run Code Online (Sandbox Code Playgroud)

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

Python 中的用法

import example

// Creating specialization
obj = example.SampleImpl()
del obj

// Creation of object using output typemap
errorCode, obj = example.SampleImpl_SampleCreate()
del obj
Run Code Online (Sandbox Code Playgroud)