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应用程序的插件,因此使用外部"东西"越少越好.
使用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,但我希望这个答案可以帮助你开始使用它.