在 SWIG/Python 中返回参数

Returning arguments in SWIG/Python

根据 Swig 文档和@Flexo 在 SWIG in typemap works, but argout does not 的精彩解释,argout 类型映射将引用参数转换为 Python 中的 return 值。

我有一个场景,其中我传递了一个 dict,然后在 typemap(in) 中将其转换为 unordered_map,然后将其填充到 C++ 库中。单步执行代码,我可以看到从 C++ returned 之后映射发生了变化,所以我想知道为什么不能将 unordered_map 原地转换回 [=12= 】 就这么通过了。还是现在有可能而我只是忽略了一些东西?

谢谢!

我有点不明白你到底在问什么,但我的理解是:

  • 你有一个 "in" 类型映射来将 Python dict 转换为 C++ unordered_map 用于某些函数参数。
  • 函数然后修改 unordered_map
  • 功能完成后,您希望 Python dict 更新为当前的 unordered_map,但在执行此步骤时遇到了问题。
  • 既然您知道如何将 dict 转换为 unordered_map,我假设您基本上知道如何使用以下方法将 unordered_map 转换回 dict Python C-API,但不知何故不确定将代码放入哪个 SWIG 类型映射。

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

  • "the argout typemap turns reference arguments into return values in Python"。不是真的,尽管它主要用于此目的。 "argout" typemap 只是提供代码来处理一些函数参数(内部称为 </code>),这些函数参数在调用 C++ 函数后 <em> 插入包装代码 <em>。将此与 "in" 类型映射进行比较,后者提供代码以将提供的 Python 参数 <code>$input 转换为 C++ 参数 </code>,这显然被插入到包装器代码 <em>在</em>调用C++函数之前。</p></li> <li><p>原来通过的Python<code>dict可以在"argout"类型映射中引用为$input,修改后的unordered_map作为 </code>(请参阅上面链接的 SWIG 文档)。</p></li> <li><p>因此,您需要做的就是为与您已有的 "in" 类型映射相同的参数签名编写一个 "argout" 类型映射,并插入代码(使用Python C-API)更新Python<code>dict($input)的内容以反映unordered_map(</code>).</p></li> <li><p>请注意,这与 "argout" 类型映射的经典用法不同,后者通常会将 <code> 转换回新的 Python dict 并将其附加到 Python return 对象,您可以通过 $result.

  • 引用它

希望对您有所帮助。如果您仍然卡在某个点上,请编辑您的问题以明确您在哪个点上遇到了问题。

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

头文件

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

   = &temp;

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

%typemap(argout) std::unordered_map<std::string, std::string>* {
 $result = PyDict_New();
 for( const auto& n : *) {
   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'}