【问题标题】:swig python output parameter by reference of char** (char**&)通过引用 char** (char**&) 的 swig python 输出参数
【发布时间】:2017-10-30 16:29:53
【问题描述】:

我在使用 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* 列表)来包装输出参数?有人可以帮忙吗?

【问题讨论】:

    标签: python list reference char swig


    【解决方案1】:

    一个问题是这一行:

    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']
    

    【讨论】:

    • 这正是我要找的!!!有用!!!非常感谢马克,帮了大忙!!!
    • 我想要两个返回参数,const char**& keys,int& result_length 虽然我可以通过 len(keys) 获得 result_length,但我更喜欢从函数 return 中获得。所以我在 dict.i 中添加了一行: $result = SWIG_Python_AppendOutput($result, PyInt_FromLong(*$2));
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 2020-07-20
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多