2016-07-24 43 views
0

根据Swig文档和@Flexo在SWIG in typemap works, but argout does not的奇妙解释,argout typemap将引用参数转换为Python中的返回值。在SWIG/Python中返回参数

我有一个场景,其中我通过dict,然后在typemap(in)转换为unordered_map,然后在C++库中填充。逐句通过代码,我可以看到映射改变后,从C++回来了,所以我不知道为什么没有,只是转换unordered_map放回原处至在通过dict的可能性。或者现在有可能,我只是忽略了一些东西?

谢谢!

回答

3

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

  • 你有一个“在”类型映射到一个Python dict转换成C++ unordered_map一些函数参数。
  • 函数然后修改unordered_map
  • 功能完成后,你想Python的dict更新为当前unordered_map,并在某种程度上有这个步骤的麻烦。
  • 既然你知道如何将dict转换为unordered_map,我假定你基本上就知道如何使用Python C-API的unordered_map转换回dict,但不知何故不确定成痛饮类型映射到放码。

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

  • “的argout类型映射变成引用参数到返回值在Python”。不是真的,尽管它主要用于此目的。一个简单地"argout" typemap供给代码来处理被的C++函数被调用之后插入包装代码一些功能参数(内部称为$1)。与供给代码所提供的Python参数$input转换成C++参数$1,其的C++函数被调用之前明显插入包装代码一个“中的”类型表进行比较。

  • 原来传递的Python dict可以在“argout”类型映射被称为$input,和改性unordered_map$1(见SWIG文档上面链接)。因此,您需要做的就是为与您已有的“in”typemap相同的参数签名编写一个“argout”类型映射表,并插入代码(使用Python C-API)来更新Python的dict$input)的内容,以反映unordered_map$1)的内容。

  • 注意,这是从传统的使用“argout” typemaps,这通常会转换$1回到一个新的Python dict并追加这Python的回报对象,你可以通过$result指不同。

我希望这有助于。如果你仍然坚持某一点,请编辑你的问题,以明确你遇到麻烦的时候。

+0

非常感谢,m7thon!第二颗子弹是我失踪的作品。从提供的Swig示例中,我认为您的最后一个项目符号是传回数据的唯一可能方式(通过使用返回值)。 –

+1

@wr m7thon与这个答案是现货。你必须注意的一件事就是让你自己记住,Python开发者(即你的绑定的用户)期望的行为是。理想情况下,你想采取最不容易混淆的路线。对我来说,通常在Python中,输入参数是不变的,因为与C++不同,你不能轻易推断(例如)通过const /不引用行为是什么。这几乎只留下了一个返回值作为选项,这通常是有道理的,因为返回值并没有用于指示设计良好的接口的成功/失败。 – Flexo

0

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

头文件

// 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 << "]\n"; 
    } 

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

接口文件

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

测试

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

输出是更新的辞典

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

请注意,在使用python3时,您可能会发现'PyString_AsString'一直返回一个空指针。您可能需要使用'PyUnicode_AsUTF8'来代替'PyString_AsString'。 –