昨天讲完了C语言实现遗传算法,没看昨天或者之前文章的点一下历史消息或者这里:
目前为止C语言的部分快要结束了,还差最后一个C语言和Python交互了,今天就讲这个。C语言和Python交互方法多了去了,有Python调用C语言,也有C语言调用Python,一般情况下Python调用C语言比较常见,毕竟Python慢,调用C语言加快速度,提高性能,这里重点讲Python调用C语言。
Python调用C语言方式我印象中也就三种方法:Python调用C语言的动态链接库(dll文件),Python调用C语言编译链接生成的可执行文件(exe文件),C语言为Python编写扩展模块。我用的就是C语言为Python编写扩展模块的方式来实现交互的,实际上那个扩展模块并不是模块,因为复用性等于0,那个模块只能用在我的项目,换成其他的项目就等于废了。当然,今天并不是要编写真真正正的Python模块,只是教大家怎么用C语言为Python写扩展模块。
首先我们需要导入必要的文件,进入anaconda3安装目录,然后找到里面有一个include文件夹,点开,复制里面所有的文件和目录。然后找到之前VS2017的项目,接着找到之前写的源码文件(Graph.h,GA.h)的目录,把之前复制的文件粘贴在此目录,然后打开之前VS2017的项目,在右边的解决方案资源管理器中右击头文件→新建→现有项,把所有文件(含有vcxproj的除外)都添加到VS2017的项目中,几乎万事大吉了,还差几个lib文件,在anaconda安装目录下还有一个libs的文件夹,进去,复制里面所有文件,粘贴到之前VS2017的项目源码文件的目录,然后在右边的解决方案资源管理器中右击头文件→新建→现有项,把所有lib文件都添加到VS2017的项目中,找起来比较麻烦。
必要的文件已经全部添加完毕,开始编写扩展库了,在右边的解决方案资源管理器右击源文件→添加→新建项,在弹出的窗口选择源文件,取个名字(我这里就叫_core.c了,实际上名字随便取,只要是c文件或者cpp文件就行)。
接下来想都不要想,必定是编写_core.c文件,首先是导入必要的头文件,代码如下:
其中GA.h,Graph.h是我之前写的,Python.h是刚刚复制并添加到项目中的。
接着就是编写必要的C语言函数了,首先要把经度最小值,纬度最小值强制转换成整数,不强转到时候会有边缘点,也就是窗口的边线上有点,不好看,像这样我点就都在窗口里面了,不仅要获取最小值,ROW这个宏定义常量到以后Python可视化的时候还是要用的,为此我就定义了一个函数getRow,获取两个最小值和ROW的函数代码如下:
然后就是Python的函数了,首先是初始化图,代码如下:
其中static是静态的意思,PyObject*表示是Python的数据类型(Python数据类型都是对象指针),core是库的名字,initGraph是方法名,两个参数都是Python的对象指针,这里两个参数用不到,self以后不需要用到(可能底层已经写好了),args就是在用Python调用的时候传入的参数,这里没有传入参数,所以args就没有必要限制了,然后是两个函数创建图和实现最短路径,虽然没有返回值,但是Python如果没有return默认返回值None,在这里必须像那个return语句一样,不可以不写,更不能瞎写(比如return NULL;)。
接下来获取点和边,先写获取边,代码如下:
在这里args参数就要有限制了上面那个if语句就是限制args,"ii"表示参数类型是一个元组,长度为2,元组中两个值都是int类型(对应关系:i:int,f:float,s:str),&i,&j表示参数的内存地址,传入两个索引,也就是必须传入两个int类型的数,如果参数不合法,直接return NULL,到了Python里面可就不是简单的return None(NULL是C语言的东西,实际上就是0,None在Python里面表示空值,不是0,两个不一样),直接报错崩溃!如果边小于10就认为是可以到达(我在这里通过返回1和0来表示可达与不可达,1:可达,0:不可达),如果可达就要以后可视化的时候画上边。
接下来就是画点和装饰getRow函数(装饰之后方便Python调用),代码如下:
获取点的函数重点是第二个return,i表示索引,x表示横坐标,y表示纵坐标,我简单的进行了移位和缩放。
还有最后一点代码如下:
第一个数组表示库中函数的一个列表,先看列表的第一个元素,"getPoint"表示以后Python调用的时候的函数名,core_getPoint表示原来的方法名,后面两个值必须那样写,剩下的都差不多,最后的那个{ NULL, NULL, 0, NULL },不能省!剩余的我相信大家看注释都知道以后编写其他名字的模块要怎么写了!
这个文件完成了,但还没完,在这里:
先选上Release和x64,如果是32位的anaconda就是x86,然后点击生成→重新生成解决方案,没有报错就说明没问题,然后就是在项目源码目录下编写_setup.py(文件名可以随便叫),代码如下:
我相信大家看了注释也能编写出其他名字的库,然后就是打开Anaconda Prompt,怎么打开之前讲过,然后切到刚刚写的源码的目录,输入命令:python _setup.py build回车,如果没有报错,该目录下有一个build的文件夹,点进去,然后再进lib.win-amd64-3.6这个文件夹,里面的一个pyd文件就是库。
最后欢迎大家扫码关注