如何在Python
中最简单地使用 DLL
文件?
具体而言,如何在不编写任何额外的包装器 C++
代码以将功能暴露给 Python
的情况下完成这一操作?
强烈建议使用原生Python
功能,而不是使用第三方库。
如何在Python
中最简单地使用 DLL
文件?
具体而言,如何在不编写任何额外的包装器 C++
代码以将功能暴露给 Python
的情况下完成这一操作?
强烈建议使用原生Python
功能,而不是使用第三方库。
为了使用方便,ctypes 是一个不错的选择。
以下是我实际编写过的 ctypes 代码示例(在 Python 2.5 中)。这是我发现的迄今为止最简单的方法,可以实现你所需求的功能。
import ctypes
# Load DLL into memory.
hllDll = ctypes.WinDLL ("c:\\PComm\\ehlapi32.dll")
# Set up prototype and parameters for the desired function call.
# HLLAPI
hllApiProto = ctypes.WINFUNCTYPE (
ctypes.c_int, # Return type.
ctypes.c_void_p, # Parameters 1 ...
ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p) # ... thru 4.
hllApiParams = (1, "p1", 0), (1, "p2", 0), (1, "p3",0), (1, "p4",0),
# Actually map the call ("HLLAPI(...)") to a Python name.
hllApi = hllApiProto (("HLLAPI", hllDll), hllApiParams)
# This is how you can actually call the DLL function.
# Set up the variables and call the Python name with them.
p1 = ctypes.c_int (1)
p2 = ctypes.c_char_p (sessionVar)
p3 = ctypes.c_int (1)
p4 = ctypes.c_int (0)
hllApi (ctypes.byref (p1), p2, ctypes.byref (p3), ctypes.byref (p4))
ctypes
库包含了所有C语言数据类型(int
, char
, short
, void*
等),可以按值或引用传递。它也可以返回特定的数据类型,虽然我的示例没有这样做(HLL API通过修改通过引用传递的变量来返回值)。
就上面显示的具体示例而言,IBM的EHLLAPI是一个相当一致的接口。
根据IBM的文档here,所有调用都通过四个void指针传递(EHLLAPI通过第四个参数,指向int
的指针将返回代码发送回来,因此,虽然我指定了int
作为返回类型,但我可以安全地忽略它)。换句话说,函数的C变体将是:
int hllApi (void *p1, void *p2, void *p3, void *p4)
这导致一个单一的、简单的ctypes
函数可以处理EHLLAPI库中提供的任何功能,但很可能其他库需要针对每个库函数设置单独的ctypes
函数。
WINFUNCTYPE
的返回值是函数原型,但仍需设置更多的参数信息(除了类型之外)。hllApiParams
中的每个元组都有一个参数“direction”(1 = 输入,2 = 输出等),一个参数名称和一个默认值 - 有关详细信息请参见ctypes
文档。
一旦您拥有了原型和参数信息,就可以创建Python“可调用”hllApi
来调用该函数。您只需创建所需的变量(在我的情况下是p1
到p4
)并使用它们调用函数即可。
hllApiParams
的作用是什么?这些元组有什么意义?这个例子中的一些内容很难与文档相对应。 - Jonathon Reinhart这个页面提供了一个使用DLL文件调用函数的非常简单的示例。
以下是详细信息的概括:
在Python中调用DLL函数非常容易。我有一个自制的DLL文件,其中包含两个函数:
add
和sub
,它们都需要两个参数。
add(a, b)
返回两个数字的加法结果
sub(a, b)
返回两个数字的减法结果DLL文件的名称将是“demo.dll”
程序:
from ctypes import*
# give location of dll
mydll = cdll.LoadLibrary("C:\\demo.dll")
result1= mydll.add(10,1)
result2= mydll.sub(10,1)
print("Addition value:"+result1)
print("Substraction:"+result2)
输出:
Addition value:11
Substraction:9
本文提供一个完整的示例,介绍了如何通过ctypes
构建一个共享库
并在Python
中使用它。文章以Windows
为例,处理DLLs
。需要两个步骤:
我考虑的共享库
如下,包含在testDLL.cpp
文件中。唯一的函数testDLL
接收一个int
并打印它。
#include <stdio.h>
extern "C" {
__declspec(dllexport)
void testDLL(const int i) {
printf("%d\n", i);
}
} // extern "C"
要从命令行使用Visual Studio
构建DLL
,请运行:
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\vsdevcmd"
设置包含路径并运行
cl.exe /D_USRDLL /D_WINDLL testDLL.cpp /MT /link /DLL /OUT:testDLL.dll
构建DLL:
Visual Studio
构建DLL或者可以使用Visual Studio
按如下方式构建DLL
:
在Python下执行以下操作:
import os
import sys
from ctypes import *
lib = cdll.LoadLibrary('testDLL.dll')
lib.testDLL(3)
Dispatch
:from win32com.client import Dispatch
zk = Dispatch("zkemkeeper.ZKEM")
zkemkeeper是系统中注册的DLL文件,之后您可以通过调用它们来访问函数:
zk.Connect_Net(IP_address, port)
ctypes是使用最简单的方法,但(mis)使用它会导致Python崩溃。如果你想快速完成某些操作,并且非常小心,那么它很棒。
我建议你查看Boost Python。是的,它需要编写一些C++代码并拥有C++编译器,但实际上你不需要学习C++就能使用它,而且你可以从Microsoft获得免费(免费啤酒)的C++编译器。
pip install pythonnet
import clr
clr.AddReference('path_to_your_dll')
# import the namespace and class
from Namespace import Class
# create an object of the class
obj = Class()
# access functions return type using object
value = obj.Function(<arguments>)
然后根据DLL中的类实例化一个对象,并访问其中的方法。