通过引用char **(char **&)来swig python输出参数

时间:2017-10-30 16:29:53

标签: python list reference char swig

我使用swig挣扎于python的c ++包装,让我卡住的是输出参数char **(char *列表)的输出参数。

我的c ++是这样的:

class dict{

    int getKeys(const char **&keys, int &result_length)
}

我知道我需要使用typemap,而且我在swig接口文件(.i)中写道:

    %{
    #include "dict.hpp"
    %}

        %apply int &OUTPUT { int & };


        %typemap(in, numinputs=0) char **& (char **temp) {
          $1 = &temp;
        }

        %typemap(argout) char**& %{
            int ntokens; 
            int itoken;

            for (ntokens = 0; *$1[ntokens] != NULL; ntokens++) { 
            }

            PyObject* temp = NULL;
            temp = $result;
            $result = PyList_New(ntokens);
            for (itoken = 0; itoken < ntokens; itoken++) {
                PyList_Append($result, PyUnicode_FromString( *$1[itoken] )); 
            }

            PyObject* list_temp = NULL;
            list_temp = $result;
            $result = PyList_New(1);

            PyList_SetItem($result, 0, temp);
            PyList_Append($result, list_temp);

            Py_DECREF(temp);
            Py_DECREF(list_temp);
        %}
        %typemap(freearg) char**& %{
            free(*$1);
        %}


    %include "dict.hpp"

编译.i文件时没问题,但是当我在python中使用它时, python.exe已停止工作

 resultCode, keys, keysCount = dict.getkeys()

我通过引用char *来成功包装输出参数:

%typemap(in, numinputs=0) char *& (char *temp) {
  $1 = &temp;
}

%typemap(argout) char*&  %{
    PyObject* temp = NULL;
    temp = $result;
    $result = PyList_New(1);
    PyList_SetItem($result, 0, temp);
    PyList_Append($result, PyUnicode_FromString(*$1));
    Py_DECREF(temp);
%}
%typemap(freearg) char*& %{
    free(*$1);
%}

但是如何通过引用char **(char *列表)来包装输出参数?有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

这一行有一个问题:

PyList_Append($result, PyUnicode_FromString( *$1[itoken] )); 

应该是:

PyList_Append($result, PyUnicode_FromString( (*$1)[itoken] ));

$result处理看起来很有趣,但我没有继续调试。我认为更好的解决方案是使用多参数类型映射。以下是我提出的测试方法(Windows操作系统):

<强> dict.hpp

#ifdef EXPORTS
#   define API __declspec(dllexport)
#else
#   define API __declspec(dllimport)
#endif

API void getKeys(const char **& keys, int& result_length);

<强> dict.cpp

#define EXPORTS
#include "dict.hpp"

API void getKeys(const char **& keys, int& result_length)
{
    result_length = 5;
    keys = new const char*[result_length];
    keys[0] = "abcd";
    keys[1] = "efgh";
    keys[2] = "ijkl";
    keys[3] = "mnop";
    keys[4] = "qrst";
}

<强> dict.i

%module dict

%{
#include "dict.hpp"
%}

%include <windows.i>

%typemap(in,numinputs=0) (const char**& keys,int& result_length) (char **temp, int len) %{
  $1 = &temp;
  $2 = &len;
%}

%typemap(argout) (const char**& keys,int& result_length) (PyObject* obj) %{
    obj = PyList_New(*$2);
    for (int itoken = 0; itoken < *$2; itoken++) {
        PyList_SET_ITEM(obj, itoken, PyUnicode_FromString( (*$1)[itoken] )); 
    }
    $result = SWIG_Python_AppendOutput($result,obj);
%}

%typemap(freearg) (const char**& keys,int& result_length) %{
    delete [] *$1;
%}

%include "dict.hpp"

输出:

Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import dict
>>> dict.getKeys()
['abcd', 'efgh', 'ijkl', 'mnop', 'qrst']