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

亡梦爱人 提交于 2021-02-08 06:57:53

问题


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

I have seen examples that call the C++ code using more high-level data structures like C++'s array. However, I simply want to pass it using basic data types like int and float *

Any simple way of doing this, with say PyBind11 or python's built-in C types?


回答1:


You can achieve this with ctypes. First create a shared object with C Api.ctypes does not support C++ but only C. This means that you can use c++ in your source code but you have to provide a C interface without C++ languages features like function overloading or name mangling. Therefor the function definitions are marked with extern "C".

Then load the shared object in python. Set argument types and result types. Finally you can call your function. Here is an example:

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

I didn't test it so possibly there are some errors but I think the idea should be clear. Here is an example I tested:

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)))


来源:https://stackoverflow.com/questions/54823040/pass-python-list-to-c-c-as-float-or-int

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!