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

2024-09-28 22:24:23 发布

您现在位置:Python中文网/ 问答频道 /正文

<>我在使用SWIG(3.0.6版)生成C++库周围的Python包装时遇到了一些麻烦。在

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

举例来说,这就是我想要的标准类型,而且它是有效的:

// .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”,但它会自动附加到结果中。太好了!在

但是,当输出类型是指向类类型的某个指针时,这似乎并不像我预期的那样有效:

^{pr2}$

问题似乎是SWIG没有以与简单类型相同的方式处理它。它仍然在包装的函数签名中显示为“input”参数。在

// 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 *&'

有人能告诉我我做错了什么吗?或者给我指出正确的方向吗?感谢您的帮助!谢谢


Tags: add类型usageresultlongswigint指向
3条回答

这不是一个答案,只是名声不够好,不能发表评论:(

因为你需要在C++中使用指针,Python没有指针(所以无论如何你不能用Python中的任何结果)做任何事情。在

是否可以按照@Jens Munk的建议,添加包装器以将指针隐藏到.h中:

class exportedClassType_ptr {
public:
    exportedClassType* ptr;
    exportedClassType_ptr( exportedClassType& input ) {
        this->ptr = &input;
    }
};

int GetClassType( const char* name, exportedClassType_ptr& resultPointer ) {
    return GetClassType( name, resultPointer.ptr );
}

修改.i文件以调用新方法:

^{pr2}$

在Python中,可以这样写:

>>> realResult = projectWrapper.exportedClassType()
>>> result = projectWrapper.exportedClassType_ptr(realResult)
>>> projectWrapper.GetClassType("name", result)

在以后的工作中使用“realResult”。在

这个问题似乎有一段时间没有得到解决,所以我想我最好能为这个问题提供一个解决方案。输出类型映射只适用于简单类型,因此通过组合inargout类型映射给出了一个解决方案。在

考虑情况,我们有一个C++类^ {< CD3>},它实现了一个C++接口^ {CD4>},这在技术上不是一个接口,因为它涉及实现一个虚拟析构函数。假设我们有一个静态函数,它返回一个错误代码和接口的实现。后者作为指针的引用,这就是上面的情况。在

接口标头:

// 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;
  };
}

实现标题:

^{pr2}$

实施:

// 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 typemap)

// 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

我想你需要用指针。我也不知道在混合类型映射和return语句时会发生什么。一个最小的示例文件tst.i

%module tst

%{

  // declaration:
  void add(long *resultLong, const long arg1,const long arg2);
  long mul(const long a, const long b);

  // the code:
  void add(long *resultLong, const long arg1,const long arg2) {
    *resultLong = arg1 + arg2;
  }
  long mul(const long a, const long b) {
    return a*b;
  }

%}

// The wrapper:
%apply (long* OUTPUT) { long* resultLong }; 
void add(long* resultLong, const long arg1,const long arg2);
long mul(const long a, const long b);

翻译后(我总是使用CMake),python中的用法是:

^{pr2}$

我认为对于标量数据类型,使用return语句而不是typemaps更好。当连接数组时,我建议使用numpy.i的预定义类型映射。在

相关问题 更多 >