需要用到的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”和“空项目”,如图:

python封装成可执行的手机程序 python可以封装成dll吗_#include

 将刚刚的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控制台应用程序,如下:

python封装成可执行的手机程序 python可以封装成dll吗_#include_02

 编写代码:

#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”。

python封装成可执行的手机程序 python可以封装成dll吗_Cython_03

二、遇到的问题:

1.问题1:

python封装成可执行的手机程序 python可以封装成dll吗_#include_04

这是由于python的环境变量没有配置好,打开windows的环境变量,新建PYTHONPATH和PYTHONHOME:

python封装成可执行的手机程序 python可以封装成dll吗_python_05

PYTHONPATH的路径为:

python封装成可执行的手机程序 python可以封装成dll吗_Cython_06

PYTHONHOME的路径为:

python封装成可执行的手机程序 python可以封装成dll吗_#include_07

重启VS!!一定要重启!!

再去测试就ok了

2、问题2:

待更新。