如何为 class 类型创建 OUTPUT 类型映射?
How to create an OUTPUT typemap for a class type?
我以前在尝试将 SWIG 的 OUTPUT 类型映射应用于 class 类型时遇到过问题,并问过这个 。
我得到的答案很有帮助,但仍然需要我让 SWIG 做类似的事情:
%apply exportedClassType& OUTPUT { exportedClassType& result };
这似乎不适用于 SWIG 3.0.6,并显示以下消息:
Warning 453: Can't apply (exportedClassType &OUTPUT). No typemaps are defined.
从查看 the documentation:
请注意 typemaps.i 文件的主要目的是支持原始数据类型。写一个这样的函数
void foo(Bar *OUTPUT);
可能没有预期的效果,因为 typemaps.i 没有为 Bar 定义 OUTPUT 规则。
这似乎不受支持。所以我想我的问题是,我需要在 interface.i 文件中定义什么类型映射组合,以便为 class 类型生成的包装代码来自:
// interface.i
%apply exportedClassType& OUTPUT { exportedClassType& result };
int getClassType(exportedClassType& result);
// interface_wrap.cxx
SWIGINTERN PyObject *_wrap_getClassType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
exportedClassType *arg1 = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
PyObject * obj0 = 0 ;
int result;
if (!PyArg_ParseTuple(args,(char *)"O:getClassType",&obj0)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1, SWIGTYPE_p_exportedClassType, 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "getClassType" "', argument " "1"" of type '" "exportedClassType &""'");
}
if (!argp1) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "getClassType" "', argument " "1"" of type '" "exportedClassType &""'");
}
arg1 = reinterpret_cast< exportedClassType * >(argp1);
result = (int)getClassType(*arg1);
resultobj = SWIG_From_int(static_cast< int >(result));
return resultobj;
fail:
return NULL;
}
// wrapper.py
def getClassType(result):
return _wrapper.getClassType(result)
getClassType = _wrapper.getClassType
更像这样的东西?
// interface.i
%apply bool& OUTPUT { bool& result };
int getSimpleType(bool& result);
// interface_wrap.cxx
SWIGINTERN PyObject *_wrap_getSimpleType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
bool *arg1 = 0 ;
bool temp1 ;
int res1 = SWIG_TMPOBJ ;
int result;
arg1 = &temp1;
if (!PyArg_ParseTuple(args,(char *)":getSimpleType")) SWIG_fail;
result = (int)getSimpleType(*arg1);
resultobj = SWIG_From_int(static_cast< int >(result));
if (SWIG_IsTmpObj(res1)) {
resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_bool((*arg1)));
} else {
int new_flags = SWIG_IsNewObj(res1) ? (SWIG_POINTER_OWN | 0 ) : 0 ;
resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg1), SWIGTYPE_p_bool, new_flags));
}
return resultobj;
fail:
return NULL;
}
// wrapper.py
def getSimpleType():
return _wrapper.getSimpleType()
getSimpleType = _wrapper.getSimpleType
我不明白需要什么 in/out/argout 类型映射,以便为我的 exportedClassType
调用 SWIG_Python_AppendOutput
等。有人可以给我一些指示吗?没有双关语的意思。
可以使用 in
和 argout
类型映射的组合来实现所需的行为。我已将其放在一个宏 class_output_typemaps
中,以便可以使用以下语法启用它
%class_output_typemaps(exportedClassType)
%apply (exportedClassType*& ARGOUT_OBJECT) {(exportedClassType *&result)}
下面给出了一个完整的例子
example.h
#pragma once
class exportedClassType {
public:
exportedClassType();
~exportedClassType();
};
int getClassType(exportedClassType*& result);
example.cpp
#include "example.h"
#include <cstdio>
int getClassType(exportedClassType*& result) {
result = new exportedClassType();
return 0;
}
exportedClassType::exportedClassType() {printf("ctor\n");}
exportedClassType::~exportedClassType() {printf("dtor\n");}
example.i
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
%include "typemaps.i"
/* %class_output_typemaps() macro
*
* It must be executed for each class CLASS_TYPE, which needs typemaps for output
*/
%define %class_output_typemaps(CLASS_TYPE)
%typemap(in, numinputs=0) (CLASS_TYPE *&ARGOUT_OBJECT) (CLASS_TYPE* temp) {
= &temp;
}
%typemap(argout) (CLASS_TYPE *&ARGOUT_OBJECT) {
CLASS_TYPE* newObj;
*(CLASS_TYPE**)&newObj = *;
PyObject* temp = NULL;
if (!PyList_Check($result)) {
temp = $result;
$result = PyList_New(1);
PyList_SetItem($result, 0, temp);
}
temp = SWIG_NewPointerObj(SWIG_as_voidptr(newObj),
$descriptor(CLASS_TYPE*),
SWIG_POINTER_OWN | 0);
PyList_Append($result, temp);
Py_DECREF(temp);
}
%enddef /* %class_output_typemaps() */
%class_output_typemaps(exportedClassType)
%apply (exportedClassType*& ARGOUT_OBJECT) {(exportedClassType *&result)}
%include "example.h"
setup.py
#!/usr/bin/env python
from distutils.core import setup, Extension
import numpy
import os
setup(name='test',
version='1.0',
ext_modules =[Extension('_example',
['example.i', 'example.cpp'],
swig_opts=['-c++'],
include_dirs = ['.'])])
使用 python setup.py build_ext --inplace
构建后,您可以使用
从 Python 中创建对象
import example
myExportedClassType = example.getClassType()[1]
我以前在尝试将 SWIG 的 OUTPUT 类型映射应用于 class 类型时遇到过问题,并问过这个
我得到的答案很有帮助,但仍然需要我让 SWIG 做类似的事情:
%apply exportedClassType& OUTPUT { exportedClassType& result };
这似乎不适用于 SWIG 3.0.6,并显示以下消息:
Warning 453: Can't apply (exportedClassType &OUTPUT). No typemaps are defined.
从查看 the documentation:
请注意 typemaps.i 文件的主要目的是支持原始数据类型。写一个这样的函数
void foo(Bar *OUTPUT);
可能没有预期的效果,因为 typemaps.i 没有为 Bar 定义 OUTPUT 规则。
这似乎不受支持。所以我想我的问题是,我需要在 interface.i 文件中定义什么类型映射组合,以便为 class 类型生成的包装代码来自:
// interface.i
%apply exportedClassType& OUTPUT { exportedClassType& result };
int getClassType(exportedClassType& result);
// interface_wrap.cxx
SWIGINTERN PyObject *_wrap_getClassType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
exportedClassType *arg1 = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
PyObject * obj0 = 0 ;
int result;
if (!PyArg_ParseTuple(args,(char *)"O:getClassType",&obj0)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1, SWIGTYPE_p_exportedClassType, 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "getClassType" "', argument " "1"" of type '" "exportedClassType &""'");
}
if (!argp1) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "getClassType" "', argument " "1"" of type '" "exportedClassType &""'");
}
arg1 = reinterpret_cast< exportedClassType * >(argp1);
result = (int)getClassType(*arg1);
resultobj = SWIG_From_int(static_cast< int >(result));
return resultobj;
fail:
return NULL;
}
// wrapper.py
def getClassType(result):
return _wrapper.getClassType(result)
getClassType = _wrapper.getClassType
更像这样的东西?
// interface.i
%apply bool& OUTPUT { bool& result };
int getSimpleType(bool& result);
// interface_wrap.cxx
SWIGINTERN PyObject *_wrap_getSimpleType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
bool *arg1 = 0 ;
bool temp1 ;
int res1 = SWIG_TMPOBJ ;
int result;
arg1 = &temp1;
if (!PyArg_ParseTuple(args,(char *)":getSimpleType")) SWIG_fail;
result = (int)getSimpleType(*arg1);
resultobj = SWIG_From_int(static_cast< int >(result));
if (SWIG_IsTmpObj(res1)) {
resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_bool((*arg1)));
} else {
int new_flags = SWIG_IsNewObj(res1) ? (SWIG_POINTER_OWN | 0 ) : 0 ;
resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg1), SWIGTYPE_p_bool, new_flags));
}
return resultobj;
fail:
return NULL;
}
// wrapper.py
def getSimpleType():
return _wrapper.getSimpleType()
getSimpleType = _wrapper.getSimpleType
我不明白需要什么 in/out/argout 类型映射,以便为我的 exportedClassType
调用 SWIG_Python_AppendOutput
等。有人可以给我一些指示吗?没有双关语的意思。
可以使用 in
和 argout
类型映射的组合来实现所需的行为。我已将其放在一个宏 class_output_typemaps
中,以便可以使用以下语法启用它
%class_output_typemaps(exportedClassType)
%apply (exportedClassType*& ARGOUT_OBJECT) {(exportedClassType *&result)}
下面给出了一个完整的例子
example.h
#pragma once
class exportedClassType {
public:
exportedClassType();
~exportedClassType();
};
int getClassType(exportedClassType*& result);
example.cpp
#include "example.h"
#include <cstdio>
int getClassType(exportedClassType*& result) {
result = new exportedClassType();
return 0;
}
exportedClassType::exportedClassType() {printf("ctor\n");}
exportedClassType::~exportedClassType() {printf("dtor\n");}
example.i
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
%include "typemaps.i"
/* %class_output_typemaps() macro
*
* It must be executed for each class CLASS_TYPE, which needs typemaps for output
*/
%define %class_output_typemaps(CLASS_TYPE)
%typemap(in, numinputs=0) (CLASS_TYPE *&ARGOUT_OBJECT) (CLASS_TYPE* temp) {
= &temp;
}
%typemap(argout) (CLASS_TYPE *&ARGOUT_OBJECT) {
CLASS_TYPE* newObj;
*(CLASS_TYPE**)&newObj = *;
PyObject* temp = NULL;
if (!PyList_Check($result)) {
temp = $result;
$result = PyList_New(1);
PyList_SetItem($result, 0, temp);
}
temp = SWIG_NewPointerObj(SWIG_as_voidptr(newObj),
$descriptor(CLASS_TYPE*),
SWIG_POINTER_OWN | 0);
PyList_Append($result, temp);
Py_DECREF(temp);
}
%enddef /* %class_output_typemaps() */
%class_output_typemaps(exportedClassType)
%apply (exportedClassType*& ARGOUT_OBJECT) {(exportedClassType *&result)}
%include "example.h"
setup.py
#!/usr/bin/env python
from distutils.core import setup, Extension
import numpy
import os
setup(name='test',
version='1.0',
ext_modules =[Extension('_example',
['example.i', 'example.cpp'],
swig_opts=['-c++'],
include_dirs = ['.'])])
使用 python setup.py build_ext --inplace
构建后,您可以使用
import example
myExportedClassType = example.getClassType()[1]