一种快速连续多次将python中的数百万项传递给C程序的方法

Mak*_*s_F 5 c python ctypes shared-libraries extend

我编写了一个python脚本,需要将数百万个项目传递给C程序,并在短时间内多次接收其输出(从1到10亿个顶点数据(整数索引和2个浮点数)快速传递500次,每次python脚本调用C程序时,我都需要将返回的值存储在变量中).我已经实现了一种读取和写入文本和/或二进制文件的方法,但它很慢而且不聪明(为什么在python脚本终止后你不需要存储数据时将文件写入hdd?).我试图使用管道,但对于大数据他们给了我错误...所以,到现在为止,我认为最好的方法是使用ctypes加载函数的能力.dll因为我从来没有创建过dll,我会想知道如何设置它(我知道很多ide都有这个模板,但是当我尝试打开它时我的wxdev-c ++崩溃.现在我正在下载Code :: Blocks)

你能告诉我我开始实施的解决方案是否正确,或者是否有更好的解决方案?我需要在python中调用的两个函数是这些

void find_vertex(vertex *list, int len, vertex* lower, vertex* highter)
{
    int i;
    *lower=list[0];
    *highter=list[1];
    for(i=0;i<len;i++)
    {
        if ((list[i].x<=lower->x) && (list[i].y<=lower->y))
            *lower=list[i];
        else
        {
            if ((list[i].x>=highter->x) && (list[i].y>=highter->y))
                *highter=list[i];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

vertex *square_list_of_vertex(vertex *list,int len,vertex start, float size)
{
    int i=0,a=0;
    unsigned int *num;
    num=(int*)malloc(sizeof(unsigned int)*len);
    if (num==NULL)
    {
        printf("Can't allocate the memory");
        return 0;
    }
    //controlls which points are in the right position and adds their index from the main list in another list
    for(i=0;i<len;i++)
    {
        if ((list[i].x-start.x)<size && (list[i].y-start.y<size))
        {
            if (list[i].y-start.y>-size/100)
            {
                num[a]=i;
                a++;//len of the list to return
            }
        }
    }

    //create the list with the right vertices
    vertex *retlist;
    retlist=(vertex*)malloc(sizeof(vertex)*(a+1));
    if (retlist==NULL)
    {
        printf("Can't allocate the memory");
        return 0;
    }
    //the first index is used only as an info container
    vertex infos;
    infos.index=a+1;
    retlist[0]=infos;

    //set the value for the return pointer
    for(i=1;i<=a;i++)
    {
        retlist[i]=list[num[i-1]];
    }

    return retlist;
}
Run Code Online (Sandbox Code Playgroud)

编辑:忘了发布顶点的类型定义

typedef struct{
    int index;
    float x,y;
} vertex;
Run Code Online (Sandbox Code Playgroud)

EDIT2:我将重新分发代码,所以我不想在python和C中的外部程序中使用外部模块.我希望尝试保持代码跨平台.该脚本是3D应用程序的插件,因此使用外部"东西"越少越好.

Sve*_*ach 7

使用ctypes或Cython来包装你的C函数绝对是要走的路.这样,您甚至不需要在C代码和Python代码之间复制数据 - C和Python部分都在同一进程中运行并访问相同的数据.让我们坚持ctypes,因为这是你的建议.此外,使用NumPy将使这更舒适.

我推断你的vertex类型看起来像这样:

typedef struct
{
    int index;
    float x, y;
} vertex;
Run Code Online (Sandbox Code Playgroud)

要将这些顶点放在NumPy数组中,可以为它定义记录"dtype":

vertex_dtype = [('index', 'i'), ('x', 'f'), ('y', 'f')]
Run Code Online (Sandbox Code Playgroud)

还要将此类型定义为ctypes结构:

class Vertex(ctypes.Structure):
    _fields_ = [("index", ctypes.c_int),
                ("x", ctypes.c_float),
                ("y", ctypes.c_float)]
Run Code Online (Sandbox Code Playgroud)

现在,ctypes您的函数原型find_vertex()将如下所示:

from numpy.ctypeslib import ndpointer
lib = ctypes.CDLL(...)
lib.find_vertex.argtypes = [ndpointer(dtype=vertex_dtype, flags="C_CONTIGUOUS"),
                            ctypes.c_int,
                            ctypes.POINTER(Vertex),
                            ctypes.POINTER(Vertex)]
lib.find_vertex.restypes = None
Run Code Online (Sandbox Code Playgroud)

要调用此函数,请创建NumPy顶点数组

vertices = numpy.empty(1000, dtype=vertex_dtype)
Run Code Online (Sandbox Code Playgroud)

和两个返回值的结构

lower = Vertex()
higher = Vertex()
Run Code Online (Sandbox Code Playgroud)

最后调用你的函数:

lib.find_vertex(vertices, len(vertices), lower, higher)
Run Code Online (Sandbox Code Playgroud)

NumPy并负责ctypes将指针传递vertices给C函数的数据开头- 无需复制.

可能你需要阅读一些文档ctypes和NumPy,但我希望这个答案可以帮助你开始使用它.