将 python 列表作为 'float*' 或 'int*' 传递给 C/C++
Pass python list to C/C++ as 'float*' or 'int*'
C/C++
void func(float* xyz1, float* xyz2,int n){
//do something
for(int i=0; i<n;i++){
printf("%f %f\n",xyz1[i],xyz2[i]);
}
}
Python
import numpy as np
n = 1000000
xyz1 = np.random.random((n,)).tolist()
xyz2 = np.random.random((n,)).tolist()
#pass above array to the C/C++ code for further processing.
func(xyz1,xyz2,n) # <-- the call to the c/c++ code
我见过使用更高级的数据结构调用 C++ 代码的示例,例如 C++ array
。但是,我只想使用 int
和 float *
等基本数据类型传递它
有什么简单的方法可以做到这一点,例如 PyBind11 或 python 的内置 C 类型?
您可以使用 ctypes
实现此目的。首先用 C Api.ctypes
创建一个共享对象,不支持 C++,只支持 C。这意味着你可以在你的源代码中使用 C++,但你必须提供一个没有 C++ 语言特性的 C 接口,比如函数重载或名称重整。因此函数定义用 extern "C"
.
标记
然后加载python中的共享对象。设置参数类型和结果类型。最后你可以调用你的函数。这是一个例子:
import ctypes
import numpy as np
n = 1000000
xyz1 = np.random.random((n,)).tolist()
xyz2 = np.random.random((n,)).tolist()
#pass above array to the C/C++ code for further processing.
Func = ctypes.CDLL("path/to/libFunc.so")
Func.func.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int]
res = Func.func(xyz1,xyz2,n) # <-- the call to the c/c++ code
我没有测试所以可能有一些错误,但我认为这个想法应该很清楚。这是我测试的一个例子:
CMakeLists.txt:
cmake_minimum_required (VERSION 3.5.1)
project (DotProduct)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_BUILD_TYPE Debug)
add_library(DotProduct SHARED src/DotProduct.cpp src/DotProduct.h)
DotProduct.h:
extern "C" double dotProduct(double* l, double* r, unsigned int len);
DotProduct.cpp:
#include "DotProduct.h"
double dotProduct(double *l, double *r, unsigned int len) {
double sum(0);
while (len--) {
sum += l[len] * r[len];
}
return sum;
}
main.py:
import ctypes
def dot_product(v1, v2):
l = len(v1)
if l != len(v2):
return 0
vec1 = (ctypes.c_double * l)(*v1)
vec2 = (ctypes.c_double * l)(*v2)
Dot_Product = ctypes.CDLL("build/lib/libDotProduct.so")
Dot_Product.dotProduct.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_uint]
Dot_Product.dotProduct.restype = ctypes.c_double
return Dot_Product.dotProduct(vec1, vec2, l)
vec1 = [2, 2]
vec2 = [2, 3]
print("{} * {} = {}".format(vec1, vec2, dot_product(vec1, vec2)))
C/C++
void func(float* xyz1, float* xyz2,int n){
//do something
for(int i=0; i<n;i++){
printf("%f %f\n",xyz1[i],xyz2[i]);
}
}
Python
import numpy as np
n = 1000000
xyz1 = np.random.random((n,)).tolist()
xyz2 = np.random.random((n,)).tolist()
#pass above array to the C/C++ code for further processing.
func(xyz1,xyz2,n) # <-- the call to the c/c++ code
我见过使用更高级的数据结构调用 C++ 代码的示例,例如 C++ array
。但是,我只想使用 int
和 float *
有什么简单的方法可以做到这一点,例如 PyBind11 或 python 的内置 C 类型?
您可以使用 ctypes
实现此目的。首先用 C Api.ctypes
创建一个共享对象,不支持 C++,只支持 C。这意味着你可以在你的源代码中使用 C++,但你必须提供一个没有 C++ 语言特性的 C 接口,比如函数重载或名称重整。因此函数定义用 extern "C"
.
然后加载python中的共享对象。设置参数类型和结果类型。最后你可以调用你的函数。这是一个例子:
import ctypes
import numpy as np
n = 1000000
xyz1 = np.random.random((n,)).tolist()
xyz2 = np.random.random((n,)).tolist()
#pass above array to the C/C++ code for further processing.
Func = ctypes.CDLL("path/to/libFunc.so")
Func.func.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int]
res = Func.func(xyz1,xyz2,n) # <-- the call to the c/c++ code
我没有测试所以可能有一些错误,但我认为这个想法应该很清楚。这是我测试的一个例子:
CMakeLists.txt:
cmake_minimum_required (VERSION 3.5.1)
project (DotProduct)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_BUILD_TYPE Debug)
add_library(DotProduct SHARED src/DotProduct.cpp src/DotProduct.h)
DotProduct.h:
extern "C" double dotProduct(double* l, double* r, unsigned int len);
DotProduct.cpp:
#include "DotProduct.h"
double dotProduct(double *l, double *r, unsigned int len) {
double sum(0);
while (len--) {
sum += l[len] * r[len];
}
return sum;
}
main.py:
import ctypes
def dot_product(v1, v2):
l = len(v1)
if l != len(v2):
return 0
vec1 = (ctypes.c_double * l)(*v1)
vec2 = (ctypes.c_double * l)(*v2)
Dot_Product = ctypes.CDLL("build/lib/libDotProduct.so")
Dot_Product.dotProduct.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_uint]
Dot_Product.dotProduct.restype = ctypes.c_double
return Dot_Product.dotProduct(vec1, vec2, l)
vec1 = [2, 2]
vec2 = [2, 3]
print("{} * {} = {}".format(vec1, vec2, dot_product(vec1, vec2)))