Python 如何调用DLL文件.pdf
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Python 如何调用DLL文件 如何 调用 DLL 文件
- 资源描述:
-
Python 调用 windows 下 DLL 详解 :Python 调用 windows 下 DLL 详解在python中某些时候需要C做效率上的补充,在实际应用中,需要做部分数据 的交互。使用python中的ctypes模块可以很方便的调用windows的dll(也包 括linux下的so等文件),下面将详细的讲解这个模块(以windows平台为例 子),当然我假设你们已经对windows下怎么写一个DLL是没有问题的。引入ctypes库 from ctypes import*假设你有了一个符合cdecl(这里强调调用约定是因为,stdcall调用约定和 cdecl调用约定声明的导出函数,在用python加载使用的加载函数是不同的,后面会说明)调用约定的DLL(名字是add.dll),且有一个导出函数A dd。建立一个Python文件DllCall.py测试:from ctypes import*dll=CDLLCadd.(111)print dll.A dd(1,102)结果:103上面是一个简单的例子。1、加载DLL上面已经说过,加载的时候要根据你将要调用的函数是符合什么调用约定的。stdcall调用约定:两种加载方式Objdl1=ctypes.windll.LoadLibrary(dllpath)Objdll=ctypes.WinDLL(dllpath)cdecl调用约定:也有两种加载方式Objdl 1=ctypes.cdll.LoadLibrary(,dllpath,/)Objdll=ctypes.CDLL(,dllpath,/)其实windll和cdll分别是WinDLL类和CD11类的对象。2、调用dll中的方法在1中加载dll的时候会返回一个DLL对象(假设名字叫Objdll),利用该对 象就可以调用dll中的方法。e.g.如果dll中有个方法名字叫A dd(注意如果经过stdcall声明的方法,如果 不是用def文件声明的导出函数的话,编译器会对函数名进行修改,这个要注意)调用:nRet=Objdll.A dd(12,15)即完成一次调用。看起来调用似乎很简单,不要只看表象,呵呵,这是因为A dd这个函数太简单了,现在假设函数需要你传入一个int类型的指针(int*),可以通过库中的byref 关键字来实现,假设现在调用的函数的第三个参数是个int类型的指针。intPara=c_ int(9)dll.sub(23,102,byref(intPara)print intPara.value如果是要传入一个char缓冲区指针,和缓冲区长度,方法至少有四种:#char*-1 szPara=create_ string_ buffer C 0*100)dll.Printinfo(byref(szPara),100);print szPara.value#char*2 sBuf=aaaaaaaaaabbbbbbbbbbbbbb5 pStr=c_ char_ p()pStr.value=sBufttpVoid=ctypes.cast(pStr,ctypes.c_ void_ p).value dll.Printinfo(pStr,len(pStr.value)print pStr.value#char*-3 strMa=0*20 FunPrint=dll.PrintinfoFunPrint.argtypes=c_ char_ p,c_ int#FunPrint.restypes=c_ void_ p nRst=FunPrint(strMa,len(strMa)print strMa,len(strMa)#char*4 pStr2=c_ char_ p(0)print pStr2.value ttpVoid=ctypes.cast(pStr,ctypes.c_ void_ p).value dll.Printinfo(pStr2,len(pStr.value)print pStr2.value3、C基本类型和ctypes中实现的类型映射表 ctypes数据类型C数据类型 c_ char charc_ short shortc_ int int c_ long long c_ ulong unsign long c_ float float c_ double double c_ void_ p void对应的指针类型是在后面加上_ P,如int*是c_ int_ p等等。在python中要实现c语言中的结构,需要用到荚。4、DLL中的函数返回一个指针。虽然这不是个好的编程方法,不过这种情况的处理方法也很简单,其实返回的都 是地址,把他们转换相应的python类型,在通过value属性访问。pchar=dll.getbuffer()szbuffer=c_ char_ p(pchar)print szbuffer.value 5、处理C中的结构体类型 为什么把这个单独提出来说呢,因为这个是最麻烦也是最复杂的,在python里 面申明一个类似C的结构体,要用到类,并且这个类必须继承自Structure。先看一个简单的例子:C里面dll的定义如下:typedef struct _ SimpleStruct(int nNo;float fVirus;char szBuffer 512;SimpleStruct,*PSimpleStruct;typedef const SimpleStruct*PCSimpleStruct;extern Cint _declspec(dllexport)PrintStruct(PSimpleStruct simp);int PrintStruct(PSimpleStruct simp)printf(nMaxNuni=%f,szContent=%s”,simp-fVirus,simp-szBuffer);return simp-nNo;Python的定义:from ctypes import*class SimpStruct(Structure):_ fields_=(nNo”,c_ int),(fVirus,c_ float),(szBuffer,c_ char*512)dll=CDLL(,A ddDll.dir,)simple=SimpStruct();simple.nNo=16simple.fVirus=3.14 15926simple.szBuffer=,magicTong0,/print dll.PrintStruct(byref(simple)上面例子结构体很简单,如果结构体里面有指针,甚至是指向结构体的指针,python里面也有相应的处理方法。下面这个例子来自网上,本来想自己写个,懒得写了,能说明问题就行:C代码如下:typedef struct char words10;keywords;typedef struct keywords*kws;unsigned int len;outStruct;extern Cint _declspec(dllexport)test(outStruct*o);int test(outStruct*o)unsigned int i=4;o-kws=(keywords*)malloc(sizeof(unsigned char)*10*i);strcpy(o-kws0.words,“The First Data);strcpy(o-kws1.words,“The Second Data);o-len=i;return 1;Python代码如下:class keywords(Structure):_ fields_=(words,c_ char*10),class outStruct(Structure):_ fields_=(kws,POINTER(keywords),(len,,c_ int),o 二 outStruct()dll.test(byref(o)print o.kws0.words;print o.kws1.words;print o.len6、例子说得天花乱坠,嘿嘿,还是看两个实际的例子。例子一:这是一个GUID生成器,其实很多第三方的python库已经有封装好的库可以调用,不过这得装了那个库才行,如果想直接调用一些A PI,对于python来说,也要 借助一个第三方库才行,这个例子比较简单,就是用C+调用win32 A pi来产生 GUID,然后python通过调用c+写的dll来获得这个GUIDC+代码如下:extern C”declspec(dllexport)char*newGUIDO;char*newGUID()static char buf64 =0;state GUID guid;if(S_ OK=:CoCreateGuid(&guid)(/,%08X-%04 X-%04 X-%02X%02X-%02X%02X%02X%02X%02X%02X,/_ snprintf(buf,sizeof(buf),,%08X-%04 X-%04 X-%02X%02X-%02X%02X%02X%02X%02X%02X,)guid.Datal,guid.Data2,guid.Data3,guid.Data40,guid.Data41,guid.Data42,guid.Data43,guid.Data44,guid.Data45,guid.Data4 6,guid.Data4 7);:MessageBox(NULL,buf,GUID,MB_ OK);)return(char*)buf;Python代码如下:def CreateGUID():创建一个全局唯一标识符类似:E06093E2-699A-4 BF2-A 325-4 F1EA DB50E18NewVersion try:#dll pathstrDHPath=sys.path0+str(os.sep)+“createguid.dll”dll=CDLL(strDlIPath)b 二 dll.newGUIDOa=c_ char_ p(b)except Exception,error:print error.returnreturn a.value 例子二:这个例子是调用kernel32.dll中的createprocessA函数来启动一个记事本进程。#coding:utf-8 一*一 from ctypes import*#定义_ PROCESSNFORMA TION 结构体class _ PR0CESS_ INF0RMA TI0N(Structure):_ fields_=(hProcess,c_ void_ p),(hThread,,c_ void_ p),(dwProcessId,c_ ulong),(dwThreadld,c_ ulong)#定义_ STA RTUPINFO结构体class _ STA RTUPINFO(Structure):_ fields_=(,cb),c_ ulong),(lpReserved,,c_ char_ p),(lpDesktop,,c_ char_ p),(IpTitle,c_ char_ p),(dwX,c_ ulong),(dwY,c_ ulong),(dwXSize,c_ ulong),(dwYSize,c_ ulong),(dwXCountChars,,c_ ulong),(dwYCountChars,c_ ulong),(dwFillA ttribute,,c ulong),(dwFlags,c_ ulong),(wShowWindow5,c_ ushort),C cbReserved2,c_ ushort),(lpReserved2,c_ char_ p),(hStdlnput,c_ ulong),(hStdOutput,c_ ulong),(hStdError,,c_ ulong)NORMA L_ PRIORITY_ CLA SS=0 x00000020#定义 NORMA L_ PRIORITY_ CLA SSkernel32=windll.LoadLibrary(,kernel32.dll)#加载 kernel32.dllCreateProcess=kernel32.CreateProcessA#获得 CreateProcess 函数地址ReadProcessMemory=kernel32.ReadProcessMemory#获得 ReadProcessMemory 函数地址WriteProcessMemory=kernel32.WriteProcessMemory#获得WriteProcessMemory 函数地址TerminateProcess=kernel32.TerminateProcess#声明结构体Processinfo=_ PR0CESS_ INF0RMA TI0N()Startupinfo 二 _ STA RTUPINFO()f ileName=,c:/windows/notepad.exe,#要进行修改的文件address=0 x004 0103c#要修改的内存地址strbuf=c_ char_ p(_)#缓冲区地址bytesRead=c ulong(0)#读入的字节数bufferSize=len(strbuf.value)#缓冲区大小#创建进程CreateProcess(fileName,0,0,0,0,NORMA L_ PRIORITY_ CLA SS,0,0,byref(Startupinfo),byref(Processinfo)Python调用Dll的儿个例子from ctypes import*fileName=,TestDll.dllfunc=cdl1.LoadLibrary(f ileName)ttprint func.HelloWorldO func.HelioWorld()(Lib.h)ttifndef LIB_ H ttdefine LIB_ Hextern C int _declspec(dllexport)add(int x,int y);ttendif(Lib.cpp)#include Lib.hint add(int x,int y)return x+y;)编译为 TestDLL.dll。然后建立一个Python文件TestDLLMain.py测试:from ctypes import*dll=CDLL(TestDLL dll)print dll.add(1,1)结果:2简单得不能再简单了!from ctypes import*fileName=,LRDlITest.dllfunc=cdll.LoadLibrary(fileName)import win32com.client#usedll=win32com.client.Dispatch(Memory.dll)搞定了几个东西1,取得鼠标位置,get_ mpos()2,移动鼠标,set_ mpos()3,鼠标左键点击,move_ click()4,键盘输入(部分搞定,那个scancode还不明白是啥意思,为什么0 x99输出的是 字符p?)代码如下codefrom ctypes import*import time#win_ start=(9,753)close_ window=(1017,4)#PUL=POINTER(c_ ulong)class KeyBdlnput(Structure):_ f ields_=(wVk”,c_ ushort),(wScan,c_ ushort),(dwFlags,c_ ulong),(“time”,c_ ulong),(dwExtralnfo,PUL)class Hardwareinput(Structure):_ fields_=(uMsg”,c_ ulong),(wParamL,c_ short),(wParamH”,c_ ushort)class Mouseinput(Structure):_ f ields_=(dx,c_ long),(dy,c_ long),(mouseData”,c_ ulong),(dwFlags,c_ ulong),(“time”,c_ ulong),(dwExtralnfo”,PUL)class Input_ I(Union):_ f ields_=(ki,KeyBdlnput),(mi”,Mouseinput),(hi,HardwareInput)class Input(Structure):_ f ields_=(type”,c_ ulong),(ii”,Input_ I)class POINT(Structure):_ f ields_=(x,c_ ulong),(y,c_ ulong)做Get Posdef get_ mpos():orig=POINT()windll.user32.GetCursorPos(byref(orig)return int(orig.x),int(orig.y)#def set mpos(pos):x,y=pos windll.user32.SetCursorPos(x,y)#def move_ click(pos,move_ back=False):origx,origy=get_ mpos()set_ mpos(pos)FInputs=Input*2 extra=c_ ulong(0)ii_=Input_ I()ii_.mi=Mouseinput(0,0,0,2,0,pointer(extra)ii2_=Input_ I()ii2_.mi=Mouseinput(0,0,0,4,0,pointer(extra)x=FInputs(0,ii_),(0,ii2_)windll.user32.Sendlnput(2,pointer(x),sizeof(x0)if move_ back:set_ mpos(origx,origy)return origx,origy#def sendkey(scancode,pressed):FInputs=Input*1extra=c_ ulong(0)ii_=Input_ I()flag=0 x8#KEY_ SCA NCODEii_.ki=KeyBdlnput(0,0,flag,0,pointer(extra)InputBox=FInputs(1,ii_)if scancode 二二 None:returnInputBox0.ii.ki.wScan=scancodeInputBox0.ii.ki.dwFlags=0 x8#KEY_ SCA NCODEif not(pressed):InputBox0.ii.ki.dwFlags|=0 x2#releasedwindll.user32.Sendlnput(1,pointer(InputBox),sizeof(InputBox01)if pressed:print%x pressed%scancodeelse:print%x released%scancodeif _name_=_main:origx,origy=get_ mpos()print 5 Orig Pos:,origx,origy#set_ mpos(9,753)#move_ click(win_ start)move_ click(800,600)time,sleep(1)sendkey(0 x99,1)ttkeyboardinput()#set_ mpos(origx,origy)Python 调用 C 的 DLL最近研究这个,准备在新部门里大用Python 了 首先用VC建立一个试验用的DLL。假设函数的参数是这样的typedef struct _ TA SK_ PA RA M日田int nTaskPriority;int nMaxNum;CHA R szContent512;_ TA SK_ PA RA M:_ TA SK_ PA RA M()电由Z eroMemory(this,sizeof(*this);卜)IL TA SK_ PA RA M,*PTA SK_ PA RA M;typedef CONST TA SK_ PA RA M*PCTA SK_ PA RA M;函数如下:extern C int Test(PCTA SK_ PA RA M para)_ 3981_ Closedniage style二DISPLA Y:noneonclick=this.style,displaynone;document.getElementByld(_ 39_ 181_ Closed_ Text,).style,display=none,;document.getElementByld(5 _ 39_ 181_ 0pen_ Image,).style,display=inline,;document.getElementByld_ 39_ 181_ 0pen_ Text,).style,displayinline,;alt=align=top”src=,http:/images, ntractedBlock.gif/printf(nTaskPriority二%d,nMaxNum=%d,szContent=%s,/,para-nTaskPriority,para-nMaxNum,para-szContent);Ireturn para-nTaskPriority;LiPython里首先这样声明对应的对象:class TA SK_ PA RA M(Structure):_ fields_=(nTaskPriority,c_ int),(nMaxNunT,c_ int),(szContent,c_ char*512)然后这样调用:cdll.LoadLibrary(C:tjDll.dll);para=TA SK_ PA RA M();para.nTaskPriority=1;para.nMaxNum=2;para.szNotifyContent=中文0;print para.szNotifyContent cdll.tjDll.Test(byref(para);如果VC的函数里要修改Python传入的参数,例如:extern C int TestlntRef(int*para)B0*para=*para+1;return*para;LPython里就这么玩:intPara=c_ int(9)print cdll.tjDll.TestlntRef(byref(intPara);print intPara.value;对于这种要修改字符串的:extern C int TestCharRef(char*para)R-LEFT:#808080 Ipx solid;BORDER-BOTTOM:#808080 Ipx solid;BA CKGROUND-COLOR:Wffffff.strcpy(para,char*test.);return 2;也不在话下:szPara=create_ string_ buffer 05*64)print cdll.tjDll.TestCharRef(byref(szPara);print szPara.value;都是从Python的ctypes的教程看来的。之前要from ctypes import*,好玩python调用dll方法 收藏在python中调用dll文件中的接口比较简单,实例代码如下:如我们有一个test,dll文件,内部定义如下:extern C int _stdcall test(void*p,int len)return len;)在python中我们可以用以下两种方式载入1.import ctypesdll=ctypes.windll.LoadLibrary(test.dll)2.import ctypesdll=ctypes.WinDII(test.dll)其中ctypes.windll为ctypes.WinDll类的一个对象,已经在ctypes模块中定 义好的。在test,dll中有test接口,可直接用dll调用即可nRst=dll.test()print nRst由于在test这个接口中需要传递两个参数,一个是void类型的指针,它指向一 个缓冲区。一个是该缓冲区的长度。因此我们要获取到python中的字符串的指 针和长度#方法一:sBuf=aaaaaaaaaabbbbbbbbbbbbbbpStr=ctypes.c_char_p()p Str.value=sBufpVoid=ctypes.cast(pStr,ctypes.c_void_p j.value nRst=dll.test(pVoid,len(pStr.value)#方法二:test=dll.testtest.argtypes=ctypes.c_char_pz ctypes.c_int test.restypes=ctypes.c_i ntnRst=test(sBut len(sBuf)如果修改test,dll中接口的定义如下:extern C(int _cdecl test(void*p,int len)(return len;)由于接口中定义的是cdecl格式的调用,所以在python中也需要用相应的类型1.import ctypesdll=ctypes.cdll.LoadLibrary(test.dll)#注:一般在linux下为test.o文件,同样可以使用如下的方法:#dll=ctypes.cdll.LoadLibrary(test.o)2.import ctypesdll=ctypes.CDII(test.dll)展开阅读全文
咨信网温馨提示:1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。




Python 如何调用DLL文件.pdf



实名认证













自信AI助手
















微信客服
客服QQ
发送邮件
意见反馈



链接地址:https://www.zixin.com.cn/doc/226582.html