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

时间:2011-12-08 17:04:49

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

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

我找到的一种方法似乎是用C ++构建类似dict的对象,例如: a boost::unordered_map,然后使用Py_BuildValue [1]方法将其翻译为Python,该方法可以生成Python dicts。但是这种方法包括将容器转换为字符串表示形式并且回到过去似乎有点太多,无法成为最高性能的解决方案!?

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

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

的代码
#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 个答案:

答案 0 :(得分:5)

  • 直接使用CPython API是:
    PyObject *d = PyDict_New()
    for (...) {
      PyDict_SetItem(d, key, val);
    }
    return d;
  • 或者通过覆盖__setitem____getitem__来编写模拟dict的python对象。在这两种方法中,使用原始的hashmap。最后,不会发生任何副本!