如何高效地在C++中构建Python字典

9 投票
1 回答
7179 浏览
提问于 2025-04-17 07:59

因为性能的原因,我想把我的Python程序的一部分移植到C++,所以我正在尝试为我的程序写一个简单的扩展。C++的部分会构建一个字典,然后需要把这个字典传递给Python程序。

我找到的一种方法是先在C++中构建一个类似字典的对象,比如说一个 boost::unordered_map,然后使用 Py_BuildValue[1] 方法把它转换成Python字典。但是这个方法需要把容器转换成字符串表示再转回来,感觉有点绕,可能不是最有效的解决方案!

所以我想问的是:在C++中构建Python字典的最有效方法是什么?我看到boost有一个Python库,支持在C++和Python之间映射容器,但到目前为止我在文档中没有找到我需要的具体内容。如果有这样的方式,我更希望直接在C++中构建一个Python字典,这样就不需要复制等操作了。不过如果最有效的方法是其他的,我也可以接受。

这是我编译成 .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()

这个字典将把字符串映射到整数。谢谢任何帮助!

1 个回答

11
  • 可以直接使用CPython的API,没问题:
    PyObject *d = PyDict_New()
    for (...) {
      PyDict_SetItem(d, key, val);
    }
    return d;
  • 或者你可以写一个Python对象,模拟字典的功能,通过重写 __setitem____getitem__ 方法。在这两种方法中,使用你原来的哈希表。最后,不会发生复制!

撰写回答