【问题标题】:How to efficiently build a Python dictionary in C++如何在 C++ 中高效地构建 Python 字典
【发布时间】:2012-01-16 02:40:53
【问题描述】:

出于性能原因,我想将我的 python 程序的一部分移植到 C++,因此我尝试为我的程序编写一个简单的扩展。 C++部分会构建一个字典,然后需要传递给Python程序。

我发现的一种方法似乎是在 C++ 中构建类似 dict 的对象,例如boost::unordered_map,然后使用 Py_BuildValue[1] 方法将其转换为 Python,该方法能够生成 Python dicts。但是这种包括将容器转换为字符串表示并返回的方法似乎有点“迫在眉睫”而不是最高效的解决方案!?

所以我的问题是:在 C++ 中构建 Python 字典最高效的方法是什么? 我看到 boost 有一个支持 C++ 和 Python 之间映射容器的 Python 库,但我没有到目前为止,在文档中找不到我需要的确切内容。如果有这种方式,我宁愿直接在 C++ 中构建 Python dict,这样就不需要复制等。但是,如果执行此操作的最佳方式是另一种方式,那我也很擅长。

这是我编译成 .dll/.pyd 的(简化的)C++ 代码:

#include <iostream>
#include <string>
#include <Python.h>
#include "boost/unordered_map.hpp"
#include "boost/foreach.hpp"

extern "C"{
typedef boost::unordered_map<std::string, int> hashmap;

static PyObject*
_rint(PyObject* self, PyObject* args)
{
    hashmap my_hashmap; // DO I NEED THIS?
    my_hashmap["a"] = 1; // CAN I RATHER INSERT TO PYTHON DICT DIRECTLY??
    BOOST_FOREACH(hashmap::value_type i, my_hashmap) {
            // INSERT ELEMENT TO PYTHON DICT
    }
    // return PYTHON DICT
}

static PyMethodDef TestMethods[] = {
    {"rint", _rint, METH_VARARGS, ""},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
inittest(void)
{
    Py_InitModule("test", TestMethods);
}

} // extern "C"

我想在 Python 中使用如下:

import test
new_dict = test.rint()

字典会将字符串映射到整数。感谢您的帮助!

【问题讨论】:

    标签: c++ python performance dictionary python-extensions


    【解决方案1】:
    • 直接使用CPython API是的:
    PyObject *d = PyDict_New() 为了 (...) { PyDict_SetItem(d, key, val); } 返回 d;
    • 或者通过覆盖__setitem____getitem__ 来编写一个模拟字典的python 对象。在这两种方法中,都使用您的原始哈希图。最后,不会发生任何复制!

    【讨论】:

    • 在 C 中实现定义 __getitem__ 的类型的一个小问题是,每次访问项目时都将创建 Python 对象,而使用 PyDict_New/PyDict_SetItem 时,您只创建一次。如果值是字符串,则必须复制数据,因此选择可能取决于如何从 Python 中使用映射。
    猜你喜欢
    • 2014-02-07
    • 1970-01-01
    • 2012-12-09
    • 2020-05-02
    • 2010-11-20
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    相关资源
    最近更新 更多