2015-10-29 14 views
15

In precedenza ho avuto problemi con il tentativo di applicare i tipamp di OUTPUT di SWIG ai tipi di classe e ho chiesto questo previous question.Come creare un typemap OUTPUT per un tipo di classe?

Le risposte che ho ricevuto ci sono stati utili, ma ancora mi richiedono di chiedere SWIG per fare qualcosa di simile:

%apply exportedClassType& OUTPUT { exportedClassType& result }; 

Questo non sembra funzionare per me su SWIG 3.0.6, con il seguente messaggio :

Warning 453: Can't apply (exportedClassType &OUTPUT). No typemaps are defined.

guardando the documentation:

Essere consapevoli del fatto che il Primar Lo scopo del file typemaps.i è di supportare i tipi di dati primitivi. Scrivere una funzione come questa void foo(Bar *OUTPUT); potrebbe non avere l'effetto desiderato poiché typemaps.i non definisce una regola OUTPUT per Bar.

Non sembra che questo sia supportato. Quindi credo che la mia domanda è, quale combinazione di typemaps ho bisogno di definire nel file interface.i in modo che il codice wrapper generato per tipi di classe va da questo:

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

a qualcosa di più simile a questo?

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

non ottengo quello IN/OUT/typemaps Argout sono necessari in modo che SWIG_Python_AppendOutput ecc è chiamato per il mio exportedClassType. Qualcuno può darmi qualche suggerimento? Nessun gioco di parole previsto.

+1

Potrebbe fornire il prototipo dei metodi che si desidera esportare. Solitamente avvolgo i costruttori e consento a SWIG di gestire il polimorfismo, ma sono riuscito a creare una fabbrica, in cui l'output è di riferimento. –

+0

Possibile duplicato di [Come applicare i typemaps di SWIG OUTPUT per i tipi di classe in Python?] (Http://stackoverflow.com/questions/32478649/how-to-apply-swig-output-typemaps-for-class-types-in -pitone) –

risposta

1

Il comportamento desiderato può essere ottenuto utilizzando una combinazione di typepap in e argout. Ho messo questo insieme in una macro class_output_typemaps tale che può essere attivata mediante la seguente sintassi

%class_output_typemaps(exportedClassType) 
%apply (exportedClassType*& ARGOUT_OBJECT) {(exportedClassType *&result)} 

Un esempio completo è il seguente

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) { 
    $1 = &temp; 
} 

%typemap(argout) (CLASS_TYPE *&ARGOUT_OBJECT) { 
    CLASS_TYPE* newObj; 
    *(CLASS_TYPE**)&newObj = *$1; 

    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 = ['.'])]) 

Dopo aver costruito utilizzando python setup.py build_ext --inplace, è possibile creare oggetti dall'interno di Python utilizzando

import example 
myExportedClassType = example.getClassType()[1] 
Problemi correlati