需要用到的IDE:pycharm、Visual Studio(我用的2015)
环境:windows、python3.5(我用的anaconda3环境)
本方案使用Cython(结合python和c),将python打包为DLL供C/C++调用。分两部分:一、流程;二、遇到的问题。
一、打包流程:
1.安装相应的Cython库:
pip install Cython
2.使用Cython编译
使用pycharm创建脚本get_add.py(本案例以简单加法运算作为演示)
def str_add(str1, str2):
return int(str1) + int(str2)
这是一个简单的将字符串转换为int求和的函数。为了使该函数能够被Cython编译,需要新建一个run.pyx文件(使用pycharm,新建空白文档,命名为“run.pyx”即可),使用Cython语法编写代码:
cdef public int str_add(const char* str1,const char* str2):
return int(str1) + int(str2)
cdef和public等都是cython关键字,这些关键字可以帮助函数可以被外部调用。然后使用下面的命令编译,生成run.h和run.c两个文件:
cython run.pxy
3.通过VS编译得到动态链接库
在得到了.c和.h文件后,我们需要为其创建一个VS DLL工程。打开VS软件,新建“Win32控制台应用程序”,命名为“test”,选择“DLL”和“空项目”,如图:
将刚刚的run.c和run.h文件复制到项目存放代码的文件夹并添加到项目中(在test项目,右键--“添加”--“现有项”)。在项目中添加一个空的dllmain.cpp,并添加如下代码:
#include <Python.h>
#include <Windows.h>
#include "run.h"
extern "C"
{
__declspec(dllexport) int __stdcall _str_add(const char * a, const char * b)
{
return str_add(a, b);
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
Py_Initialize();//dll初始化的时候调用,这是python3的写法,python2改成,initrun()。参见生成的run.h
PyInit_run();
break;
case DLL_PROCESS_DETACH:
Py_Finalize();
break;
}
return TRUE;
}
右键项目,属性,进入VC++目录标签页。在包含路径中添加Python的include路径,和lib库,具体如下:
1)VC++ 目录。包含目录:D:\Anaconda3\include ;库目录:D:\Anaconda3\libs
2)C/C++,常规。附加包含目录:D:\Anaconda3\include。
3)链接器,常规。附加库目录:D:\Anaconda3\libs。
4)链接器,输入。附加依赖项:(如果是Release)python35.lib;(如果是Debug)python35_d.lib,并在D:Anaconda3\libs\下的python35.lib复制,重命名为python35_d.lib。
配置完成后,选择VS编辑器的“生成”--“生成解决方案”。
成功后,DLL文件在项目文件夹下的“x64/Release”中(我用的x64平台,Release方式,找自己对应平台和配置的文件夹)。
4.DLL调用
建立另一个工程对刚生成的dll进行测试。打开VS新建Win32控制台应用程序,如下:
编写代码:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
typedef int(*pAdd)(const char * a, const char * b);
HINSTANCE hDLL = LoadLibrary(_T("test3.dll"));
cout << "hDLL:" << hDLL << endl;
if (hDLL)
{
pAdd pFun = (pAdd)GetProcAddress(hDLL, "_str_add");
cout << "pFun:" << pFun << endl;
const char* stra = "12";
const char* strb = "22";
if (pFun)
{
int i = pFun(stra, strb);
cout << "i = " << i << endl;
}
}
system("pause");
return 0;
}
根据dll选择x86或x64平台,进行release编译后可以得到输出结果“i = 34”。
二、遇到的问题:
1.问题1:
这是由于python的环境变量没有配置好,打开windows的环境变量,新建PYTHONPATH和PYTHONHOME:
PYTHONPATH的路径为:
PYTHONHOME的路径为:
重启VS!!一定要重启!!
再去测试就ok了
2、问题2:
待更新。