在SWIG / Python中返回参数

Returning arguments in SWIG/Python

根据swig文档和在typemap工作中对swig的精彩解释,但是argout不是由@flexo提供的,argouttypemap在python中将引用参数转换为返回值。

我有一个场景,在其中我通过一个EDCOX1,1,然后在EDCOX1,3,3中转换成一个EDCOX1×2,然后在C++ LIB中填充。通过代码,我可以看到映射在从C++返回之后发生了变化,所以我想知道为什么不可能将EDCOX1的2返回到就绪的EDCX1 1中。或者现在有可能,我只是忽略了一些事情?

谢谢!


我有点困惑你到底在问什么,但我的理解是:

  • 您有一个"in"类型映射,将Python EDCOX1的0度转换为C++函数unordered_map,用于某些函数参数。
  • 然后,该函数修改unordered_map
  • 完成该函数后,您希望将python dict更新为当前的unordered_map,并且不知何故在该步骤中遇到了问题。
  • 既然您知道如何将dict转换为unordered_map,我假设您基本上知道如何使用python c-api将unordered_map转换回dict,但不知何故不确定将代码放入哪个swig类型映射。

因此,在这些假设下,我将尽力帮助:

  • "argout类型映射将引用参数转换为python中的返回值"。不是真的,尽管它主要用于这个目的。一个"AgOutt"类型映射只提供代码来处理一些函数参数(内部称为EDCOX1(9)),在调用C++函数后插入到包装代码中。将此与一个"in"类型映射进行比较,该类型映射提供代码以将提供的Python参数EDCOX1(10)转换成C++参数EDCOX1(9),在调用C++函数之前,它显然被插入到包装代码中。

  • 原来传递的python dict在"argout"类型图中称为$input,修改后的unordered_map称为$1(见上面链接的swig文档)。

  • 因此,您所需要做的就是为与您已有的"in"类型映射相同的参数签名编写一个"argout"类型映射,并插入代码(使用python c-api)以更新python dict($input的内容,以反映unordered_map的内容($1)。

  • 请注意,这与传统的"argout"类型映射不同,后者通常会将$1转换回新的python dict,并将其附加到python返回对象,可以由$result引用该对象。

我希望这有帮助。如果你在某一点上仍有困难,请编辑你的问题,明确你在哪一点上遇到了困难。


我很清楚用户已经解决了他的问题,但这里有一个解决方案。可以引入一些输入验证,以避免输入字典的非字符串值。

头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// File: test.h
#pragma once

#include <iostream>
#include <string>
#include <unordered_map>

void method(std::unordered_map<std::string, std::string>* inout) {

  for( const auto& n : (*inout) ) {
    std::cout <<"Key:[" << n.first <<"] Value:[" << n.second <<"]
"
;
  }

  (*inout)["BLACK"] ="#000000";
};

接口文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// File : dictmap.i
%module dictmap

%{
  #include"test.h"
%}

%include"typemaps.i"

%typemap(in) std::unordered_map<std::string, std::string>* (std::unordered_map<std::string, std::string> temp) {

  PyObject *key, *value;
  Py_ssize_t pos = 0;

  $1 = &temp;

  temp = std::unordered_map<std::string, std::string>();
  while (PyDict_Next($input, &pos, &key, &value)) {
    (*$1)[PyString_AsString(key)] = std::string(PyString_AsString(value));
  }
}

%typemap(argout) std::unordered_map<std::string, std::string>* {
 $result = PyDict_New();
 for( const auto& n : *$1) {
   PyDict_SetItemString($result, n.first.c_str(),
            PyString_FromString(n.second.c_str()));
 }
}
%include"test.h"

试验

1
2
import dictmap
out = dictmap.method({'WHITE' : '#FFFFFF'})

输出是更新的字典

1
2
In[2]: out
Out[3] : {'BLACK': '#000000', 'WHITE': '#FFFFFF'}