天天看点

Python调用动态库(dll)实战准备动态库Python调用动态库

准备动态库

使用Visual Studio 2017创建项目,如图所示,选中动态链接库后点击确定。

Python调用动态库(dll)实战准备动态库Python调用动态库

创建好的工程如下图所示

Python调用动态库(dll)实战准备动态库Python调用动态库

添加Dll2.h头文件

Python调用动态库(dll)实战准备动态库Python调用动态库

并在头文件中输入代码:

#pragma once

#include <windows.h>

/*  To use this exported function of dll, include this header
*  in your project.
*/

#ifdef BUILD_DLL    // 记下这个
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C"
{
#endif
	unsigned int DLL_EXPORT log2_d(unsigned int n);
	long long DLL_EXPORT sum(int x, int y);
	DLL_EXPORT char* reverse(char *s);
#ifdef __cplusplus
}
#endif
           

由于在python中只能调用C,因此需要利用extern C指示编译器将代码按C进行编译。

Python调用动态库(dll)实战准备动态库Python调用动态库

在Dll2.cpp文件中添加代码如下:

// Dll2.cpp: 定义 DLL 应用程序的导出函数。
#include "stdafx.h"
#define BUILD_DLL  //此处需要进行宏定义,名称和头文件中保持一致,且需要在includet头文件之前。
#include "Dll2.h"
#include <stdio.h>

unsigned int DLL_EXPORT log2_d(unsigned int n) {
	unsigned int result = 0;  unsigned int cp = n;
	if (n & 0xffff0000) { result += 16; n >>= 16; }
	if (n & 0x0000ff00) { result += 8; n >>= 8; }
	if (n & 0x000000f0) { result += 4; n >>= 4; }
	if (n & 0x0000000c) { result += 2; n >>= 2; }
	if (n & 0x00000002) { result += 1; n >>= 1; }
	if (cp > 1 << result)  result++;
	return result;
}

long long DLL_EXPORT sum(int x, int y) {
	return x + y;
}

DLL_EXPORT char* reverse(char* s){   # python调用dll使用的库ctypes不支持string,因此需要使用char*
	char t,            
	*p = s,                     
	*q = (s + (strlen(s) - 1)); 
	while (p < q){
		t = *p;  
		*p++ = *q;
		*q-- = t;
	}
	return (s);
}
           

查看python位数,我的是64位的,在使用Visual Studio编译动态库时要和python位数一致。

Python调用动态库(dll)实战准备动态库Python调用动态库
Python调用动态库(dll)实战准备动态库Python调用动态库

编译动态库

Python调用动态库(dll)实战准备动态库Python调用动态库

在工程目录下找到编译生成的动态库文件。

Python调用动态库(dll)实战准备动态库Python调用动态库

Python调用动态库

用python的ctypes,调用动态库

创建一个python测试文件,并将Dll2.dll文件拷贝到和python测试文件同个目录下,如图。

Python调用动态库(dll)实战准备动态库Python调用动态库

调用动态库里的函数需要指定参数的输入类型和返回类型,参数类型名也有所不同,下图是参数类型名对照表。

Python调用动态库(dll)实战准备动态库Python调用动态库
from ctypes import *
import ctypes

dllPath = ctypes.cdll.LoadLibrary("Debug/Dll2.dll")

x = 100
y = 200
print(dllPath.sum(x, y))

n = 1024
print(dllPath.log2_d(n))

dllPath.reverse.argtypes = [c_char_p]  // 指定参数的输入类型
dllPath.reverse.restype = c_char_p     // 返回类型
s = b"hello world"                     // 注意此处字符串要改成二进制
print(dllPath.reverse(s))
print(bytes.decode(dllPath.reverse(s)))
           

测试结果如下所示

Python调用动态库(dll)实战准备动态库Python调用动态库