将 python list 作为 'float*' 或 'int*' 传递给 C/C++

Pass python list to C/C++ as 'float*' or 'int*'

本文关键字:C++ int python list float 作为      更新时间:2023-10-16

c/c

void func(float* xyz1, float* xyz2,int n){
     //do something
     for(int i=0; i<n;i++){
        printf("%f %fn",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 的array)调用C 代码的示例。但是,我只想使用intfloat *

等基本数据类型传递它。

有任何简单的方法,例如pybind11或python的内置C类型?

您可以使用ctypes实现此目标。首先使用C API创建共享对象。ctypes不支持C ,而只能C。这意味着您可以在源代码中使用C ,但是您必须提供一个没有C 语言功能的C界面,例如功能过载或名称Mangling。因此,函数定义用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)))