Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何处理C++;返回类型std::vector<;int>;在Python ctypes中?_C++_Python_Ctypes - Fatal编程技术网

C++ 如何处理C++;返回类型std::vector<;int>;在Python ctypes中?

C++ 如何处理C++;返回类型std::vector<;int>;在Python ctypes中?,c++,python,ctypes,C++,Python,Ctypes,我找不到ctypes如何弥合std::vector和Python之间的鸿沟;在互联网上没有提到的组合。这是不好的做法,是不存在还是我遗漏了什么 C++:xxx.cpp #include <fstream> #include <string> using namespace std; extern "C" std::vector<int> foo(const char* FILE_NAME) { string line; std::vector&

我找不到ctypes如何弥合
std::vector
和Python之间的鸿沟;在互联网上没有提到的组合。这是不好的做法,是不存在还是我遗漏了什么

C++:xxx.cpp

#include <fstream>
#include <string>
using namespace std;
extern "C" std::vector<int> foo(const char* FILE_NAME)
{
    string line;
    std::vector<int> result;
    ifstream myfile(FILE_NAME);
    while (getline(myfile, line)) {
      result.push_back(1);
    }

    return(result);
}

基本上,从动态加载的库返回C++对象不是一个好主意。要在Python代码中使用C++ <代码> vector < /Cube >,必须教Python处理C++对象(并且这包括可以用新版本的C++编译器或STL改变的对象的二进制表示)。
ctypes
允许您使用C类型与库交互。不是C++。 也许这个问题可以通过
boost::python
解决,但是使用纯C进行交互看起来更可靠

特别的原因是速度很重要。我正在创建一个 应该能够处理大数据的应用程序。20万排 必须根据300个值(200k乘以300矩阵)计算缺失。我 相信,但如果我错了,请纠正我,C++将是显著的 更快

好的,如果你从一个大文件中读取,你的进程将主要是IO绑定的,因此Python和C之间的时间安排可能不会有太大的不同

下面的代码

result = []
for line in open('test.txt'):
    result.append(line.count('NA'))
…运行速度似乎与我在C中所能破解的任何东西一样快,尽管它使用了一些我并不太熟悉的东西

处理200000行只需不到一秒钟的时间,尽管我很想看看是否可以编写一个速度更快的C函数


更新

如果您想在C中完成这项工作,并最终得到一个Python列表,那么您可以自己使用来构建列表,而不是构建一个
std::vector
,然后再转换为Python列表

一个只返回从0到99的整数列表的示例

// hack.c

#include <python2.7/Python.h>

PyObject* foo(const char* filename)
{
    PyObject* result = PyList_New(0);
    int i;

    for (i = 0; i < 100; ++i)
    {
        PyList_Append(result, PyInt_FromLong(i));
    }

    return result;
}
用法示例

>>> from ctypes import *
>>> dll = CDLL('./hack.so')
>>> dll.foo.restype = py_object
>>> dll.foo('foo')
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]

不管这种方法是否真的提供了更快的执行时间,我将解释一下您可以如何执行它。基本上,创建一个指向C++的代码指针>向量< /> >,它可以通过C函数与Python接口。然后,您可以在Python类中包装C++代码,隐藏<代码> cType < /C> > /P>的实现细节。 我在Python类中包含了我认为有用的魔法方法。您可以选择删除它们或添加更多以满足您的需要。不过,析构函数很重要

C++
//vector_python.cpp
#包括
#包括
#包括
#包括
使用名称空间std;
外部“C”void foo(向量*v,常量字符*文件名){
弦线;
ifstream myfile(文件名);
while(getline(myfile,line))v->push_back(1);
}
外部“C”{
向量*new_向量(){
返回新向量;
}
void delete_向量(向量*v){
不能推回(i);
}
}
将其编译为共享库。在Mac OS X上,这可能看起来像

g++ -c -fPIC vector_python.cpp -o vector_python.o
g++ -shared -Wl,-install_name,vector_python_lib.so -o vector_python_lib.so vector_python.o
python
相关:我刚从那个页面出来,它的相关程度就像一个Python Numpy问题与另一个Python Numpy问题的相关程度一样。在这种情况下,提到的线程没有帮助。其他建议?请注意,它确实提到了std::vector,但在某种意义上是将它连接到python中的列表。我的理解是,使用CyType,Python将能够使用cType对象?与其说它与使用STD::向量,就像一般使用C++一样。C++没有任何有意义的方式支持cType。最好是用C风格的接口创建C函数。你可能会一起破解一些有用的东西,但最好是创建一个
int
数组,并返回指向该数组的指针。我刚才也注意到了这一点,运行类似的代码,Python花了大约8秒才完成。但是,我仍然对正确的C++方式感到好奇。作为一个Python列表,1秒是令人惊奇的。我不在乎它是否会对其他人寻找C++答案有帮助,这是令人印象深刻的。让我想知道我什么时候才真正需要C++。应该是微不足道的,使用类似的C++代码。超棒的答案!
>>> from ctypes import *
>>> dll = CDLL('./hack.so')
>>> dll.foo.restype = py_object
>>> dll.foo('foo')
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]
g++ -c -fPIC vector_python.cpp -o vector_python.o
g++ -shared -Wl,-install_name,vector_python_lib.so -o vector_python_lib.so vector_python.o
from ctypes import *

class Vector(object):
    lib = cdll.LoadLibrary('vector_python_lib.so') # class level loading lib
    lib.new_vector.restype = c_void_p
    lib.new_vector.argtypes = []
    lib.delete_vector.restype = None
    lib.delete_vector.argtypes = [c_void_p]
    lib.vector_size.restype = c_int
    lib.vector_size.argtypes = [c_void_p]
    lib.vector_get.restype = c_int
    lib.vector_get.argtypes = [c_void_p, c_int]
    lib.vector_push_back.restype = None
    lib.vector_push_back.argtypes = [c_void_p, c_int]
    lib.foo.restype = None
    lib.foo.argtypes = [c_void_p]

    def __init__(self):
        self.vector = Vector.lib.new_vector()  # pointer to new vector

    def __del__(self):  # when reference count hits 0 in Python,
        Vector.lib.delete_vector(self.vector)  # call C++ vector destructor

    def __len__(self):
        return Vector.lib.vector_size(self.vector)

    def __getitem__(self, i):  # access elements in vector at index
        if 0 <= i < len(self):
            return Vector.lib.vector_get(self.vector, c_int(i))
        raise IndexError('Vector index out of range')

    def __repr__(self):
        return '[{}]'.format(', '.join(str(self[i]) for i in range(len(self))))

    def push(self, i):  # push calls vector's push_back
        Vector.lib.vector_push_back(self.vector, c_int(i))

    def foo(self, filename):  # foo in Python calls foo in C++
        Vector.lib.foo(self.vector, c_char_p(filename))
>>> from vector import Vector
>>> a = Vector()
>>> a.push(22)
>>> a.push(88)
>>> a
[22, 88]
>>> a[1]
88
>>> a[2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "vector.py", line 30, in __getitem__
    raise IndexError('Vector index out of range')
IndexError: Vector index out of range
>>> a.foo('file.txt')
>>> a
[22, 88, 1, 1, 1]
>>> b = Vector()
>>> ^D
destructor called in C++ for 0x1003884d0
destructor called in C++ for 0x10039df10