背景

最近需要用python写个脚本程序(win10 环境),需要调用现成的dll库完成这项任务,对于一直在Linux平台上开发程序的本人来说,从没有过使用dll的经历(不得不说还是so大法好),遇到了一些坎坷。最终搞定,记录一下,获取能对其他同样经历的人有所帮助。

制作dll库

程序要win10下运行,不多说,直接安装VS2019,多年未见,不得不说vs2019果真不错,安装可以根据自己的需要做的很小。比起之前的vs IDE,运行速度貌似有一些提升(纯感觉,未实证)。对于习惯了用SourceInsight阅读源码的本人来说,对以前vs启动要半天,调试过程非常卡顿的坏印象根深蒂固。vs2019的一上手有种异常的顺畅感,难道仅因为最近升级了i7的PC?

前面都是废话,首先上来【创建新项目】,选择【Windows桌面向导】,【创建】,应用程序选择【动态链接库(.dll)】,空项目,然后确定即可。具体参考如下图,是不是一样这么做?当然不是,但如果自己不这么配置选择,比如创建了新的空项目,那意味着自己写完程序又要做一些乱七八糟的配置,非常让人心烦。吐糟一下,为什么就不能像linux一样,把make的过程不加修饰的交给开发呢....

创建dll工程

创建代码

本次测试,将涉及无参数函数、基础类型参数函数、结构体类型参数、回调函数。这些是C/C++基本的函数形态,本次脚本任务也确实需要这些调用,因此一并进行了测试。So,我们的动态库需要导出这些函数供我们使用python调用。

1.创建pycall.h头文件

首先,创建新的.h文件,并将需要的函数声明为导出,由于python的ctypes只能识别C风格代码,因此导出函数应该以extern "C"来声明导出函数为C风格。头文件为:

pycall.h

#pragma once

struct stuTest {

char* name;

int age;

char address[32];

};

typedef void (*callbakc) (int a, int b);

extern "C"

{

__declspec(dllexport) int __stdcall printTest(int a); //int参数

__declspec(dllexport) void __stdcall setPointContent(char* b);//char*引用

__declspec(dllexport) int __stdcall getStrLen(const char* str);//char*指针

__declspec(dllexport) int __stdcall struckParamTest(stuTest* struck_pointer);//传结构体指针

__declspec(dllexport) void __stdcall testCallback(int a, callbakc func);//回调函数

}

__declspec(dllexport)声明该函数为导出函数,只有导出函数可以被调用

__stdcall 声明传参方式,一般跨语言的调用尽量使用std,具体扩展知识网上查寻即可

2.创建pycall.cpp文件

#include

#include"pycall.h"

#include

#include

#include

#include

#pragma warning(disable:4996) //允许使用strcpy

using namespace std;

int __stdcall printTest(int a)

{

FILE* stream;

char tmp[128];

memset(tmp,0,sizeof(tmp));

errno_t err = fopen_s(&stream, "D:\\test.txt", "w+");

snprintf(tmp,sizeof(tmp),"haha:%d\n",a);

fprintf(stream,"%s", tmp);

fputs("测试函数fputs输出... \n", stream);

fclose(stream);

printf("hello world!-%d-\n", a);

return a + 10;

}

void __stdcall setPointContent(char* b)

{

strcpy(b,"hello world!");

}

int __stdcall getStrLen(const char* str)

{

std::string tmp(str);

return tmp.length();

}

int __stdcall struckParamTest(stuTest* struck_pointer)

{

char* str1 = new char[20];

strcpy(str1, "name");

strcpy(struck_pointer->address,"hehe");

struck_pointer->age = 33;

struck_pointer->name = str1;

return 0;

}

void __stdcall testCallback(int a, callbakc func)

{

if(a == 1)

func(20,30);

else if (a == 2) {

for(int i = 0 ;i < 20;i++)

func(20+i, 30+i);

}

}

生成dll库文件

VS2019上操作【生成】->【生成解决方案】,生成dll库文件。但这里有一点要非常注意:如果python安装的是32位的,那么生成dll时应该配置为x86;如果python安装的是64位的,那么生成的dll应该配置为x64,以生成64位的dll文件。

一定要注意位数的匹配,如果python是64位的,dll是32位的,会报错:非法的32位win程序

Python中调用dll中的函数

python调用dll中的函数,本次使用ctypes模块来完成。这其中还有比较多的知识,简单介绍一下:

ctypes中的数据类型和C类型以及python类型均有对应关系,当调用一个C函数时,根据C函数的类型,调用ctypes方法时候需要匹配ctype的类型。例如:

当调用C函数char* fuc(int a)时,加载库得到pdll,python中调用时,则应该这么做:

pdll.func.argtypes = [c_int]

pdll.func.restype = c_char_p

pdll.func(10);

但对于基本类型,ctypes会尝试做类型转换,转换失败抛出异常ArgumentError.详细内容可以参见python手册的ctypes章节。类型之间的转换关系表简单参考:

ctypes type

C type

Python type

_Bool

bool (1)

char

1-character bytes object

wchar_t

1-character string

char

int

unsigned char

int

short

int

unsigned short

int

int

int

unsigned int

int

long

int

unsigned long

int

__int64 or long long

int

unsigned __int64 or unsigned long long

int

size_t

int

ssize_t or Py_ssize_t

int

float

float

double

float

long double

float

char * (NUL terminated)

bytes object or None

wchar_t * (NULterminated)

string or None

void *

int or None

python测试脚本程序

# -*- coding: utf-8 -*-

from ctypes import *

pDll = windll.LoadLibrary("mydll.dll")

#传数字

printTnull = pDll.printTest

print(printTnull(28))

#传字符串

pStr = c_char_p(b"abcdef")

print(pDll.getStrLen(pStr))

#传字符串数组

pointSet = pDll.setPointContent

out = create_string_buffer(1024,0);

pointSet(out)

print(out.value)

#结构体引用

class PyStruct(Structure):

_fields_=[("name",c_char_p),("age",c_int),("address",c_char*32)]

ptS1 = PyStruct()

ptS1.name = b"lwz"

ptS1.age = 20

ptS1.address = b"hangzhou"

pyS1_cstruct = byref(ptS1)

print(pDll.struckParamTest(pyS1_cstruct))

print(ptS1.age)

print(ptS1.address)

print(ptS1.name)

#回调函数

def callFuc(a,b):

print("value is:",a,b)

# ctypes通过 CFUNCTYPE 支持回调函数,定义返回值与参数,第一个参数表示返回值,void为None,第二参数为回调函数的参数为结构体指针

CALLBACK = CFUNCTYPE(None,c_int,c_int)

# 定义回调函数

#callBackFunc = CALLBACK(callFuc)

pDll.testCallback(2,CALLBACK(callFuc))

python如何调用dll库中的函数_Python调用dll库接口-ctypes方法相关推荐

  1. python调用js库中的函数_Python 调用JS文件中的函数

    Python 调用JS文件中的函数 1.安装PyExecJS第三方库 2.导入库:import execjs 3.调用JS文件中的方法 Passwd = execjs.compile(open(r&q ...

  2. 【Python——类】 同一个类中一个函数里调用另一个函数的方法

    [Python-类] 同一个类中一个函数里调用另一个函数的方法 class Solution:def a(self):self.b() # 注意这种写法:self.类名def b(self):prin ...

  3. python中pixels函数_Python的PIL库中getpixel方法的使用

    getpixel函数是用来获取图像中某一点的像素的RGB颜色值,getpixel的参数是一个坐标点.对于图象的不同的模式,getpixel函数返回的值有所不同. 1.RGB模式 from PIL im ...

  4. python调用php命令行,python调用php函数 python怎样调用php文件中的函数详解

    前言 python调用php代码实现思路:php文件可通过在terminal中使用php命令行进行调用,因此可使用python开启子进程执行命令行代码.函数所需的参数可通过命令行传递. 测试环境 1. ...

  5. 【C 语言】动态库封装与设计 ( 动态库调用环境搭建 | 创建应用 | 拷贝动态库相关文件到源码路径 | 导入头文件 | 配置动态库引用 | 调用动态库中的函数 )

    文章目录 一.在 Visual Studio 2019 中创建 " 控制台应用 " 程序 二.拷贝 xxx.lib.xxx.dll.xxx.h 到源码路径 三.导入 xxx.h 头 ...

  6. python echo函数_python如何调用php文件中的函数详解

    前言 python调用php代码实现思路:php文件可通过在terminal中使用php命令行进行调用,因此可使用python开启子进程执行命令行代码.函数所需的参数可通过命令行传递. 测试环境 1. ...

  7. python调用php_python如何调用php文件中的函数详解

    前言 python调用php代码实现思路:php文件可通过在terminal中使用php命令行进行调用,因此可使用python开启子进程执行命令行代码.函数所需的参数可通过命令行传递. 测试环境 1. ...

  8. VC6中调用.dll文件中的函数——傻瓜式教程

    决这一问题上的 帮助. 先声明下,我此前从未涉及过Windows 下的编程,所以对于懂了这么点东西就要写篇文章, 大家可不要鄙视啊. 实际上,写这篇文章的最主要原因是,我觉得调用.dll 文件里的函数 ...

  9. 动态链接库DLL创建及导出函数、调用DLL

    1.动态链接库(dll)概述 没接触dll之前觉得它很神秘,就像是一个黑盒子,既不能直接运行,也不能接收消息.它们是一些独立的文件,其中包含能被可执行程序或其他dll调用来完成某项工作的函数,只有在其 ...

最新文章

  1. C++走向远洋——39(指向学生类的指针)
  2. 分享一些 WINDOWS 资源站点(备用)
  3. 论分层思想在各行各业的应用
  4. flex 设置换行flex-wrap
  5. Javascript 学习笔记 2: 标识语句
  6. mysql数据库入门教程(10):标识列和事务
  7. matlab与STK互联(不使用connect软件的互联)
  8. Jupyter notebook基础教程(启动,汉化,操作)
  9. 孤读Paper——《CenterNet:Objects as Points》
  10. Java中的反射与JDK动态代理
  11. j2Cache线上异常问题排查记录
  12. wap手机网页(网站)自适应中部悬浮小广告代码【靠右侧】
  13. 从技术走向管理——李元芳履职记
  14. 如何查询计算机上次登录时间,怎么查看电脑的上一次开机时间
  15. iOS调用系统相机将英文改成中文
  16. 关于论坛数据库的设计
  17. Kafka 2.8.0 正式发布,增加了哪些新特性?
  18. java 抽象final_java抽象、接口 和final
  19. JS 怎么控制 checkbox 选中的问题
  20. ElasticSearch的学习笔记并整合SpringBoot做测试

热门文章

  1. Spring Bean详细讲解 什么是Bean?
  2. Spring中bean的含义是什么啊?
  3. 王小川新AI公司浮出水面:成立「五季智能」,召集搜狗旧部,水下估值接近独角兽...
  4. IEduChina 2019国际教育展暨国际教育论坛相约北京
  5. 皖西学院计算机证书,安徽皖西学院2017年3月计算机二级考试报名时间
  6. Stm32F103R6之实时时钟(RTC)
  7. 一种语言 适合任何时候使用 — Haxe特性杂谈
  8. C++ 单链表(带头结点)
  9. 贷款违约预测-Task2 数据分析
  10. 【软件测试基础理论知识】1.2.常见的软件开发模型之———增量模型(渐增模型)、螺旋模型