相关文章推荐
会开车的企鹅  ·  python ...·  2 天前    · 
会开车的企鹅  ·  php - Laravel Query ...·  5 月前    · 
会开车的企鹅  ·  PolarDB 数据库内核月报·  7 月前    · 
会开车的企鹅  ·  js 字符串 string \n \\ ...·  10 月前    · 
会开车的企鹅  ·  PHP: ...·  1 年前    · 
会开车的企鹅  ·  analysis of rtsp | ...·  1 年前    · 
文雅的沙滩裤  ·  WKWebView拦截请求资源 ·  50 分钟前    · 
独立的眼镜  ·  如何连接Babelfish for RDS ...·  2 小时前    · 
发财的蛋挞  ·  Microsoft Azure Data ...·  2 小时前    · 
冷冷的投影仪  ·  Secure an ASP.NET ...·  2 小时前    · 
不羁的生姜  ·  PSPSDK 开发的时候出现 ...·  2 小时前    · 

在网上搜索很多关于pythonDLL文件调用的问题,大多给出的都是DLL文件的编写,然后python调用,但是在调用中遇到的一些问题却很少有提及,下面将给出在python调用DLL文件时遇到的一些问题等。

ctypes官网: https://docs.python.org/3.6/library/ctypes.html?highlight=ctypes#module-ctypes

python dll文件调用网上出现的最多的是和下面这个博客链接里面的内容差不多: https://blog.csdn.net/magictong/article/details/3075478

1、错误:OSError: [WinError 193] %1 不是有效的 Win32 应用程序。

Traceback (most recent call last):
  File "G:/AutoTool/driver/Instrument_dynamic.py", line 12, in <module>
    dll = cdll.LoadLibrary("Dll1.dll")
  File "E:\python\python3\lib\ctypes\__init__.py", line 426, in LoadLibrary
    return self._dlltype(name)
  File "E:\python\python3\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 不是有效的 Win32 应用程序。

当遇到这个问题的时候,是因为程序当当前的编辑运行环境不匹配,拿DLL文件调用来说,你在64位的python环境下调用32位的DLL文件肯定是不行的,这时你需要把python环境换成32位的。

2、C/C++的DLL文件编写,简单的小示例。

#include "stdafx.h"
#include <windows.h>
#include <iostream>
typedef struct _SimpleStruct
	int    nNo;
	float  fVirus;
	char   szBuffer[2];
} SimpleStruct, *PSimpleStruct;
typedef const SimpleStruct*  PCSimpleStruct;
extern "C" int  __declspec(dllexport) PrintStruct(PSimpleStruct simp);
int PrintStruct(PSimpleStruct simp)
	printf("nMaxNum=%f,szContent=%s", simp->fVirus, simp->szBuffer);
	return simp->nNo;

        3、python调用编写好的DLL文件,可以帮助理解DLL文件的调用。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# author:SingWeek
from ctypes import *
class SimpStruct(Structure):
    _fields_ = [("nNo", c_int),
                ("fVirus", c_float),
                ("szBuffer", c_wchar)]#“”中的命名可以自己指定
dll = CDLL("Dll1.dll")
# print(dll.PrintStruct)
simple = SimpStruct()
simple.nNo = 16
simple.fVirus = 3.1415926
simple.szBuffer = "x"
out=dll.PrintStruct(byref(simple))
print(out)

        4、python下通过from ctypes import *调用DLL文件的注意事项:

        想要正确调用dll文件,你要找到正确的调用约定,必须查看C头文件或要调用的函数的文档。整数、字节对象和(unicode)字符串是唯一可以在这些函数调用中直接用作参数的本地Python对象。它们都不作为C语言NULL指针传递,字节对象和字符串作为指针传递给包含它们的数据的内存块(char*或wchar_t*)。Python整数作为平台默认的C int类型传递,它们的值被屏蔽以适合于C类型。在继续使用其他参数类型调用函数之前,我们必须了解更多关于ctypes数据类型的信息。

        Python ctypes 数据类型表

ctypes type

C type

Python type

c_bool

_Bool

bool (1)

c_char

char

1-character bytes object

c_wchar

wchar_t

1-character string

c_byte

char

int

c_ubyte

unsigned char

int

c_short

short

int

c_ushort

unsigned short

int

c_int

int

int

c_uint

unsigned int

int

c_long

long

int

c_ulong

unsigned long

int

c_longlong

__int64 or long long

int

c_ulonglong

unsigned __int64 or unsigned long long

int

c_size_t

size_t

int

c_ssize_t

ssize_t or Py_ssize_t

int

c_float

float

float

c_double

double

float

c_longdouble

long double

float

c_char_p

char * (NUL terminated)

bytes object or None

c_wchar_p

wchar_t * (NUL terminated)

string or None

c_void_p

void *

int or None

        5、function ‘test’ not found!,是因为dll文件中没有对应函数,The specified module could not be found或者function ‘***’ not found

        6、Procedure called with not enough arguments (** bytes missing) or wrong calling convention,在调用DLL文件中的对应函数的时候,参数传递出错,可能是参数少了,也可能是参数类型不对等引起的,此时需要核对DLL文件中的参数结构形式。

         7、首先有这个函数会出现一串地址print(cdll.kernel32.GetModuleHandleA),如果向dll调用的函数中传入的参数发生错误,会出现如下问题。

        8、重点:在dll文件中的调用方式有几种,他们分别对应不同的约定。其中cdll用于加载遵守cdecl标准函数调用约定的连接库;windll用于加载遵循stdcall调用约定的动态链接库,oledll和windll完全相同,只是会默认其载入的函数会统一返回一个windows result错误编码。在python中除了cdll,还可以用pydll功能相同,大小写的区别在于小写需要添加LoadLibrary进行dll文件调用;大写的可以直接将dll文件名放进局可以了。

        stdcall调用约定:stdcall很多时候被称为pascal调用约定,因为pascal是早期很常见的一种教学用计算机程序设计语言,其语法严谨,使用的函数调用约定就是stdcall。在Microsoft C++系列的C/C++编译器中,常常用PASCAL宏来声明这个调用约定,类似的宏还有WINAPICALLBACKstdcall调用约定声明的语法为(以前文的那个函数为例):int __stdcall function(int a,int b)

        stdcall的调用约定意味着:1)参数从右向左压入堆栈,2)函数自身修改堆栈 3)函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸。注意不同编译器会插入自己的汇编代码以提供编译的通用性,但是大体代码如此。

        cdecl调用约定:cdecl调用约定又称为C调用约定,是C语言缺省的调用约定,它的定义语法是:

int function (int a ,int b) //不加修饰就是C调用约定,int __cdecl function(int a,int b)//明确指出C调用约定。cdecl调用约定的参数压栈顺序是和stdcall是一样的,参数首先由右向左压入堆栈。所不同的是,函数本身不清理堆栈,调用者负责清理堆栈。

        9、DLL文件查看:可以在这个链接中下载dll查看器http://www.dependencywalker.com/。可以查看Dll中的相关函数等,方便对对应dll的功能函数进行编写。下载后点击运行,直接将DLL文件放进来或者打开后就可以查看。

10、在python中除了通过byref传入指针地址外,还有一个函数pointer。原文链接:http://www.pythontip.com/blog/post/9835/

  在进行Python开发的过程中,很可能遇到调用C++ DLL库的情况(为了提高效率),那么需要通过ctypes这个包,调用 ctypes.cdll.LoadLibrary(“path”)或者 ctypes.CDLL(“path”),   然后可能就会碰到下面这个问题:大致意思就是找不到指定的库文件,但是这路径就是这样的。 Traceback (m ctypes调用dll动态链接库时报错:FileNotFoundError: Could not find module 'D:\Desktop\RhoplusDLL\Rhoplus.dll' (or one of its dependencies). Try using the full path with constructor syntax. 1 创建C++工程生成dll库编译生成2pythoN调用dll库#!/bin/env python# -*- coding: utf-8 -*-import ctypes#获取路径import os#pathnow=os.getcwd() #获取当前路径pathnow=os.path.abspath('ConsoleApplication1.dll') #获取指定文件名字的全路径pathnow=p... 介绍如何通过ctypes模块调用 C, C++ DLL SO 动态链接库,介绍了ctypes 各种数据类型,包含字符串,指针,枚举等,如何转换 C/C++ 函数参数,特别是结构体与指针,如何转换为python格式,以将转实参传入dll 函数,获取并解析返回值, 用于调用DLL, SO动态链接库,或者 第3方SDK库,与硬件接口 如题,安装过atari_py,但在import时出现"lib\ctypes\__init__.py", line 364, in __init__ self._handle = _dlopen(self._name, mode) OSError: [WinError 126] 找不到指定的模块。" 打印了self.name,其值为D:\software\Anaconder3\envs\testrl\lib\site-packages\atari_py\ale_interface/ale_c.dll from _ctypes import Union, Structure, Array ImportError: DLL load failed while importing _ctypes: 找不到指定的模块。 第三方厂商提供的库文件, 一个USB接口的小票打印机T532, TxPrnMod.dll TxPrnMod.lib wrapper.dll 一个串口的 读取智能卡的读卡器TTCE_M100, M100_DLL.dll,M100_DLL.lib, 通过 win7 ... python 可以调用C++的DLL 动态链接库,从而达到与c++语言交互的目的。 python调用C++编译生成的DLL动态链接库,我们需要借助ctypes库。 ctypes是一个用于Python的外部函数库,它提供C兼容的数据类型,并允许在DLL或共享库中调用函数。 假如我们在外面定义了一个myTest.dll文件,计算两个数之和。 那么 我们python 如何调用DLL文件呢。 下面是具体的方法,代码也是比较少,引入ctypes包即可。 from ctypes import * # -------
 
推荐文章