swig python 通过引用 char** (char**&) 输出参数
swig python output parameter by reference of char** (char**&)
我在使用 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) {
= &temp;
}
%typemap(argout) char**& %{
int ntokens;
int itoken;
for (ntokens = 0; *[ntokens] != NULL; ntokens++) {
}
PyObject* temp = NULL;
temp = $result;
$result = PyList_New(ntokens);
for (itoken = 0; itoken < ntokens; itoken++) {
PyList_Append($result, PyUnicode_FromString( *[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(*);
%}
%include "dict.hpp"
编译.i文件没有问题,但是在python中使用时,python.exe已经停止工作
resultCode, keys, keysCount = dict.getkeys()
我通过引用 char* 成功包装了输出参数:
%typemap(in, numinputs=0) char *& (char *temp) {
= &temp;
}
%typemap(argout) char*& %{
PyObject* temp = NULL;
temp = $result;
$result = PyList_New(1);
PyList_SetItem($result, 0, temp);
PyList_Append($result, PyUnicode_FromString(*));
Py_DECREF(temp);
%}
%typemap(freearg) char*& %{
free(*);
%}
但是如何通过引用char**(char*的列表)来包装输出参数?有人可以帮忙吗?
一个问题是这一行:
PyList_Append($result, PyUnicode_FromString( *[itoken] ));
应该是:
PyList_Append($result, PyUnicode_FromString( (*)[itoken] ));
$result
处理看起来很有趣,但我没有继续调试。我认为更好的解决方案是使用多参数类型映射。这是我想出的测试方法 (Windows OS):
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) %{
= &temp;
= &len;
%}
%typemap(argout) (const char**& keys,int& result_length) (PyObject* obj) %{
obj = PyList_New(*);
for (int itoken = 0; itoken < *; itoken++) {
PyList_SET_ITEM(obj, itoken, PyUnicode_FromString( (*)[itoken] ));
}
$result = SWIG_Python_AppendOutput($result,obj);
%}
%typemap(freearg) (const char**& keys,int& result_length) %{
delete [] *;
%}
%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']
我在使用 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) {
= &temp;
}
%typemap(argout) char**& %{
int ntokens;
int itoken;
for (ntokens = 0; *[ntokens] != NULL; ntokens++) {
}
PyObject* temp = NULL;
temp = $result;
$result = PyList_New(ntokens);
for (itoken = 0; itoken < ntokens; itoken++) {
PyList_Append($result, PyUnicode_FromString( *[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(*);
%}
%include "dict.hpp"
编译.i文件没有问题,但是在python中使用时,python.exe已经停止工作
resultCode, keys, keysCount = dict.getkeys()
我通过引用 char* 成功包装了输出参数:
%typemap(in, numinputs=0) char *& (char *temp) {
= &temp;
}
%typemap(argout) char*& %{
PyObject* temp = NULL;
temp = $result;
$result = PyList_New(1);
PyList_SetItem($result, 0, temp);
PyList_Append($result, PyUnicode_FromString(*));
Py_DECREF(temp);
%}
%typemap(freearg) char*& %{
free(*);
%}
但是如何通过引用char**(char*的列表)来包装输出参数?有人可以帮忙吗?
一个问题是这一行:
PyList_Append($result, PyUnicode_FromString( *[itoken] ));
应该是:
PyList_Append($result, PyUnicode_FromString( (*)[itoken] ));
$result
处理看起来很有趣,但我没有继续调试。我认为更好的解决方案是使用多参数类型映射。这是我想出的测试方法 (Windows OS):
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) %{
= &temp;
= &len;
%}
%typemap(argout) (const char**& keys,int& result_length) (PyObject* obj) %{
obj = PyList_New(*);
for (int itoken = 0; itoken < *; itoken++) {
PyList_SET_ITEM(obj, itoken, PyUnicode_FromString( (*)[itoken] ));
}
$result = SWIG_Python_AppendOutput($result,obj);
%}
%typemap(freearg) (const char**& keys,int& result_length) %{
delete [] *;
%}
%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']