C++ vector to Python 3.3
C++ vector to Python 3.3
我想从c++脚本中获得一个python列表,例如,[1,2,3,4]
。我编写了c++脚本,它返回一个向量。
如何连接两端没有SWIG/SIP/Cython/和其他?
是否可以更容易地将c++编译为。exe或elf文件,然后从命令行调用,让。exe创建一个包含矢量的。txt并使用python读取它?
我的观点是,我只需要c++中的一个非常小的函数来对大数据进行繁重的计算。要做到这一点,最不痛苦、最短的方法是什么?
编辑:举个例子。Python将给c++提供一个文件名字符串("foo.txt"),然后它将读取文件的上下文(200,000行乘300列),计算缺失的数量,然后将每行缺失的数量返回给Python。这将产生一个包含200,000个数字的列表。他们之间如何进行这种沟通?
为了完整起见,这是我仍然想知道如何去做的事情:
- 将python文件名字符串传递给c++
- 接收c++ python字符串 在c++中创建矢量
- 返回Python
- Python中的接收向量
这现在可能是没有意义的,我在你的其他问题上发布了类似的东西,但我已经为Python 3.3和c++改编了这个版本,而不是Python 2.7和C。
如果你想返回一个Python列表对象,并且由于你正在构建一个可能非常长的列表(200,000项),那么在c++代码中构建Python列表可能更有效,而不是构建std::vector
然后稍后将其转换为Python列表。
根据你其他问题中的代码,我建议使用这样的代码…
// foo.cpp
#include <python3.3/Python.h>
#include <fstream>
#include <string>
using namespace std;
extern "C"
{
PyObject* foo(const char* FILE_NAME)
{
string line;
ifstream myfile(FILE_NAME);
PyObject* result = PyList_New(0);
while (getline(myfile, line))
{
PyList_Append(result, PyLong_FromLong(1));
}
return result;
}
}
编译与…
$ g++ -fPIC -shared -o foo.so foo.cpp -lpython3.3m
…还有一个用法的例子…
>>> from ctypes import *
>>> foo = CDLL('./foo.so')
>>> foo.foo.restype = py_object
>>> foo.foo(b'foo.cpp')
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
…虽然如果您需要将现有的std::vector
转换为Python列表,您可以通过将向量的长度传递给PyList_New()
来预先分配Python列表所需的内存,然后使用PyList_SetItem()
而不是PyList_Append()
。
我能想到的唯一其他方法是…
在Python中预先分配一块RAM,并让c++函数填充值,就像在qarma的答案中一样,但您必须事先知道要分配多少RAM。您可以选择一个任意的值,但是考虑到文件中的行数事先不知道,这个数字可能太大或太小。
在c++中堆分配
std::vector
,并返回指向第一个元素的指针,以及元素的数量,但是你必须写第二个函数来释放RAM,一旦你完成了它。
无论哪种方式,您仍然有将'返回'数组转换为Python列表的开销,因此您不妨自己完成。
定义您的入口点extern "C"
并使用ctypes
下面是一个示例,数据从Python传递,c++代码对数据进行排序,然后Python返回结果:
#include <sys/types.h>
#include <algorithm>
extern "C" {
void foo(float* arr, size_t len);
}
void foo(float* arr, size_t len)
{
// if arr is input, convert to C++ array
// crazy C++ code here
std::sort(arr, arr+len);
// if arr is output, convert C++ array to arr
}
编译你的代码到一个共享对象(libxxx. exe)。linux上是libxxx.dll, win上是libxxx.dll。),然后动态加载它,并通过ctypes传入/传出数据:
import ctypes
import posix
# Darwin .dylib; Linux .so; Windows .dll; use sys.platform() for runtime detection
libxxx = ctypes.CDLL("./libxxx.so")
libxxx.foo.argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.c_size_t]
libxxx.foo.restype = None
data = ctypes.ARRAY(ctypes.c_float, 100)()
# write someting into data[x]
import random
for i in range(100): data[i] = random.random()
print data[:3], "...", data[-3:]
libxxx.foo(data, len(data))
# read out from data[x]
print data[:3], "...", data[-3:]
ctypes
的伟大之处在于它从2.5开始就与Python捆绑在一起了,你不需要任何额外的库。
如果你想使用更高级的东西,看看cffi
你做对了。
你有两个可执行文件吗?
最好将其保存到中间文件中。锁定文件,从c++代码中写入文件。解锁并从Python中读取。
如果你只是想从python运行,你可以考虑扩展python:
用c++扩展Python
也可以选择通过套接字来传递,但是如果您只想传递列表,那么这可能有点多余。
您可以使用python中的subprocess模块从c++ exe文件中读取输出。例如:
c++文件:#include <iostream>
using namespace std;
int main()
{
int a[]={1,2,3,4};
cout<<"[";
for(int i=0; i<3; i++)
cout<<a[i]<<",";
cout<<a[3]<<"]";
return 0;
}
那么你的python脚本将是:
import subprocess
a=subprocess.check_output("c++compiledfile")
l=eval(a)
print l
你可以在进程间通信中使用字符串:
使用Python中的subprocess.check_output()函数来检查c++程序的输出,并将文件名作为参数传递:
import subprocess
from time import clock
ti=clock()
txt_fname='foo.txt'
# pass the filename string to a c++ program, and receive vector in python
output=subprocess.check_output(["./prog", txt_fname])
result = eval(output) # convert the str_result to a vector/list
tf=clock()
print(result)
print(format(tf-ti, '.3f'))
c++代码:#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
int main(int argc, char *argv[])
{
// receive python string in c++
char* txt_fname = argv[1];
/* // read matrix from file in c++
FILE *f_matrix = fopen(txt_fname, "r");
// ... [done by the question's author!]
if (f_matrix!=NULL){
fclose(f_matrix);
}*/
// create the vector in c++
int n=200000;
std::vector<int> vect(n);
// or: int vect[];
// ... [done by the question's author!]
// return the vector to python
std::cout << "[";
for (int i=0; i<n; i++)
std::cout << vect[i] << ", ";
std::cout << "]";
return 0;
}
EDIT:添加计时器并将"ast.literal_eval()"替换为"eval()",因为实际上eval()在这种情况下更快,并且与python 3.3兼容。
- Python str to C++ to Python str
- Python to C++ Data structure API
- "Cannot convert Python object argument to type '<typename>'" - 使用 Cython 包装 C++ 类时出错
- PyBind - Python to C++ interface
- Python class inheritance to c++
- Python bool conversion to C++ (pybind11)
- Arduino Float Value to Python using NRF24L01
- SWIG INOUT types (C++ to Python)
- tensorflow::Tensor to python Tensor or numpy.nd_array
- SWIG C++ to Python:生成 Python 列表的子类
- swig c to python:抛出一个中止的实例后终止
- PyBind11: boost::multiprecision::cpp_int to Python
- swig c++ to python with openssl/bn.h
- Swig C++ to python:编译一堆.cpp和.h文件
- Python ConfigParser to C++
- 带有swig-to-python模块的c++类
- Swig C to Python ImportError: undefined symbol
- C++ Qt equivalent to python unpack_from
- Python* to boost::python::object
- SEGUID from python to c++