最近有个项目需要使用到python来调用C++编写动态连接库

无奈在百度上的办法百花齐放

跟着做也频频出错

所以自己研究了一下调用的规则

————————————下面是正文——————————————

一.环境描述

       首先说明下编译的环境:C++编译环境是 —>VS2015、python编译环境是 —> pycharm 

二.C++编写DLL

       在编写动态库之前,我们要先明确所编写的DLL是32bit还是64bit的,博主当时就是因为pycharm是64位的而DLL是32位的而调用失败,细节决定成败......确定好之后,先新建一个 “WIN32项目”

               

如何用C制作python库 c++编写python库_C/C++

        点击确定之后进而按照以下图示进行选择,当然,也可以不创建一个空项目,只是博主喜欢啥都是自己写的,这样比较有安全感,有兴趣可以研究下其他方式:

                                    

如何用C制作python库 c++编写python库_调用约定_02

          之后在创建一个.cpp以及.h头文件,具体怎么创建我就不在此描述,如何不知道怎么创建的话,自行百度:

                                                                            

如何用C制作python库 c++编写python库_C/C++_03

          创建完文件之后,我们先对头文件(Sum.h)进行编写:

#include <iostream>
#define Export extern "C" _declspec(dllexport)

Export int _stdcall SumTest(int a, int b);

在此处,我们首先来了解下几个关键字的使用:

1. extren "C" : 使用该关键字在于C++的编译器会对符号进行修饰,导出的 _declspec(dllexport/dllimport) function(void ,void) 函数会被改编为 _declspec(dllexport/dllimport) function _void,_void ,此举将给编译器取得函数的地址带来不便,所以,使用 extren "C" 来限定函数根据C的方式进行编译,防止出现符号修饰。

2._declspec(dllexport/dllimport) : 用于Windows中动态库中,用于将函数或者类声明为导出函数(dllexport)/导入函数(dllimport),以供其他程序调用。

3. _stdcall :该关键字属于C/C++ 的调用约定中的一种,调用约定决定了:A.函数压栈的顺序 B.产生修饰名的方式 C.决定了函数的参数由调用者还是被调用者push出栈,想要了解更多的调用约定的知识可自行百度,在此不再累述。使用调用约定绝大多数并不会影响到程序的逻辑,但是如果对于跨语言进行编程时,则现得十分重要,每个编译器所默认的调用约定都不一样,VC/VS 默认 _cdecl 的方式,Windows API 默认 _stdcall 的方式,所以在编写DLL时,为了与Windows API保持一致,一般使用 _stdcall 的调用约定。

 

       编写完头文件之后,再编写源文件(Sum.cpp):

#include "Sum.h"

Export int _stdcall SumTest(int a, int b)
{
	return a + b;
}

        在写完测试函数之后 “ 生成解决方案 ” ,等待片刻即可生成一个后缀为.dll 的动态库文件(注意,在生成解决方案时记得查看生成的文件是32bit 还是64bit 的):

   

如何用C制作python库 c++编写python库_如何用C制作python库_04

          将图示框住的动态库文件复制粘贴到新建的python目录下:

如何用C制作python库 c++编写python库_python_05

           然后编写python的调用代码:

from ctypes import *

dll = WinDLL('DLLTest.dll')
a = c_int(3)
b = c_int(4)
print(dll.SumTest(a,b))

           注意:如果DLL中使用的 _stdcall 调用约定,在python中需要使用 windll.LoadLibrary()/WinDll() 进行调用;

                      如果DLL中使用的 _cdecl 调用约定,在python中需要使用 CDll() 进行调用;

                      其他调用约定的导入方式可自行百度~   

 

编写完代码之后进行编译,编译成功:

如何用C制作python库 c++编写python库_C/C++_06