python - 如何使用 SWIG 从 C++ 无序映射生成 Python 字典?

标签 python c++ swig typemaps swig-typemap

我正在尝试使用 swig 将无序映射包装在 python 字典中:

// UsingAnUnorderedMap.h
#ifndef LEARNSWIG_USINGUNORDEREDMAP_H
#define LEARNSWIG_USINGUNORDEREDMAP_H

#include <unordered_map>
#include <string>


std::unordered_map<std::string, int> makeStringToIntMap(){
    return std::unordered_map<std::string, int>{
        {"first", 4},
        {"second", 5},
    };
}

#endif //LEARNSWIG_USINGUNORDEREDMAP_H
//UsingAnUnorderedMap.i
%module UsingUnorderedMap

%{
#include "UsingUnorderedMap.h"
#include <iostream>
#include <unordered_map>
%}

%include "std_string.i"
%include "std_pair.i"
%include "std_unordered_map.i"

%template(StringToIntMap) std::unordered_map<std::string,int>;


%include "UsingUnorderedMap.h"
%typemap(out) StringToIntMap {
    PyDictObject* dict = PyDict_New($input);
    for (auto &item: StringToIntMap){
        PyDict_SetItem(dict, PyUnicode_FromString(item.first), item.second);
    }
    $result = dict;
}
# testUsingAnUnorderedMap.py
import sys

sys.path += [
    r"D:\LearnSwig\install-msvc\UsingUnorderedMap"
]

import UsingUnorderedMap

print(type(UsingUnorderedMap.makeStringToIntMap())) 

这会产生

<class 'UsingUnorderedMap.StringToIntMap'>

即它只是忽略类型映射。从技术上讲,StringToIntMap 的行为与 Python 字典几乎相同 - 据我所知,但我认为 Python 字典中的 Python 用户会感到舒适,所以如果这是一个直接的版本会更好字典。有人对如何实现这一目标有任何指示吗?

为方便起见,您可以使用以下 CMake 代码构建此代码。请注意,我使用命令 -DSWIG_EXECUTABLE=/path/to/swig.exe 构建此文件。

# CMakeLists.txt
set(Python_ROOT_DIR "C:/Miniconda3")
find_package(Python COMPONENTS Interpreter Development NumPy)
        message("Python_EXECUTABLE ${Python_EXECUTABLE}")

find_package(SWIG 4.0.0 REQUIRED
        COMPONENTS python
        )

include(UseSWIG)

set_property(SOURCE UsingUnorderedMap.i PROPERTY CPLUSPLUS ON)

swig_add_library(UsingUnorderedMap
        LANGUAGE python
        TYPE MODULE
        SOURCES UsingUnorderedMap.i UsingUnorderedMap)

set_target_properties(UsingUnorderedMap
        PROPERTIES LANGUAGE CXX)

target_include_directories(UsingUnorderedMap PUBLIC
        ${Python_INCLUDE_DIRS}
        ${CMAKE_CURRENT_SOURCE_DIR}
        )
target_link_libraries(UsingUnorderedMap PUBLIC ${Python_LIBRARIES})

install(TARGETS UsingUnorderedMap DESTINATION UsingUnorderedMap)
install(FILES
        ${CMAKE_CURRENT_BINARY_DIR}/UsingUnorderedMap.py
        ${CMAKE_CURRENT_SOURCE_DIR}/testUsingUnorderedMap.py
        DESTINATION UsingUnorderedMap)

最佳答案

这里有一个小例子,展示了 std::unordered_map 到 python 字典的转换

%module dictmap
%{
  #include "test.h"
%}

%typemap(out) std::unordered_map<std::string, std::string> (PyObject* obj) %{
  obj = PyDict_New();
  for (const auto& n : $1) {
    PyObject* strA = PyUnicode_FromString(n.first.c_str());
    PyObject* strB = PyUnicode_FromString(n.second.c_str());
    PyDict_SetItem(obj, strA, strB);
    Py_XDECREF(strA);
    Py_XDECREF(strB);
  }
  $result = SWIG_Python_AppendOutput($result, obj);
%}
%include "test.h"

小型内联函数

#pragma once
#include <string>
#include <unordered_map>

std::unordered_map<std::string, std::string> makeStringMap() {
  return std::unordered_map<std::string, std::string> {
    {"first", "hello"},
    {"second", "world"},
  };
}

我希望你能看到自己做错了什么。您将返回一个使用空 $input 创建的空字典。我不确定您是否需要定义 PyObject 参数,但我总是这样做,以防需要与另一个类型映射一起使用。

关于python - 如何使用 SWIG 从 C++ 无序映射生成 Python 字典?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66731276/

相关文章:

python - 使用 matplotlib colormap 和 pandas dataframe.plot 函数

c++ - 多线程快速排序

swig - PyBind - 重载函数

java - 是否可以一起使用 Java、SWIG 和 Rust?

php - 从 PHP Web 应用程序调用 C++ 库 : system() vs SWIG PHP extension?

python - 如何搜索 yaml 文件中的特定字符串和内容

java - hive 中的python udf

python - 让用户上传 Python 脚本执行

c++ 11 段错误(核心转储),但 c++ 17 没有

c++ - 从串行读取但只获取最新数据