在 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'}
根据 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>
转换回新的 Pythondict
并将其附加到 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'}