在Python中使用DLL文件的最简单方法是什么?
具体来说,如何在不编写任何额外的包装器c++代码将功能公开给Python的情况下实现这一点呢?
本机Python功能比使用第三方库更受欢迎。
在Python中使用DLL文件的最简单方法是什么?
具体来说,如何在不编写任何额外的包装器c++代码将功能公开给Python的情况下实现这一点呢?
本机Python功能比使用第三方库更受欢迎。
ctypes将是最容易使用的东西,但(错误地)使用它会使Python崩溃。如果你试图快速做某事,而且你很小心,这很好。
我鼓励你去看看Boost Python。是的,它要求你写一些c++代码,并有一个c++编译器,但你实际上不需要学习c++来使用它,你可以从微软得到一个免费的(就像啤酒一样)c++编译器。
为了便于使用,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文档,所有调用都传递四个void指针(EHLLAPI通过第四个参数返回返回代码,这是一个指向int的指针,因此虽然我指定int作为返回类型,但可以安全地忽略它)。换句话说,函数的C变体是:
int hllApi (void *p1, void *p2, void *p3, void *p4)
这使得一个简单的ctypes函数能够做EHLLAPI库提供的任何事情,但其他库可能需要为每个库函数设置单独的ctypes函数。
WINFUNCTYPE的返回值是一个函数原型,但是您仍然需要设置更多的参数信息(除了类型之外)。hllApiParams中的每个元组都有一个参数“direction”(1 =输入,2 =输出,等等)、一个参数名和一个默认值——详细信息请参阅ctypes doco
一旦你有了原型和参数信息,你就可以创建一个Python“可调用的”hllApi来调用函数。您只需创建所需的变量(在我的例子中是p1到p4)并使用它们调用函数。
本页有一个从DLL文件调用函数的非常简单的示例。
为了完整起见,在这里解释一下细节:
It's very easy to call a DLL function in Python. I have a self-made DLL file with two functions: add and sub which take two arguments. add(a, b) returns addition of two numbers sub(a, b) returns substraction of two numbers The name of the DLL file will be "demo.dll" Program: 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) Output: Addition value:11 Substraction:9
也许与调度:
from win32com.client import Dispatch
zk = Dispatch("zkemkeeper.ZKEM")
其中zkemkeeper是在系统上注册的DLL文件… 之后,你可以通过调用函数来访问它们:
zk.Connect_Net(IP_address, port)
构建一个DLL并使用ctypes在Python下链接它
我给出了一个完整的示例,说明如何通过ctypes在Python下构建共享库并使用它。我考虑Windows的情况并处理dll。需要两个步骤:
使用Visual Studio的编译器从命令行或IDE构建DLL; 使用ctypes链接Python下的DLL。
共享库
我考虑的共享库如下所示,包含在testDLL.cpp文件中。唯一的函数testDLL只接收一个int并输出它。
#include <stdio.h>
extern "C" {
__declspec(dllexport)
void testDLL(const int i) {
printf("%d\n", i);
}
} // extern "C"
从命令行构建DLL
使用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。
从IDE构建DLL
或者,DLL可以使用Visual Studio构建,如下所示:
文件->新建->项目; 已安装->模板-> Visual c++ -> Windows -> Win32 -> Win32Project; 下一个; 应用程序类型-> DLL; 附加选项->空项目(选择); 附加选项->预编译头(取消选择); 项目->属性->配置管理器->主动解决方案平台:x64; 项目—>属性—>配置管理器—>主用解决方案配置:发布。
在Python下链接DLL
在Python下,执行以下操作
import os
import sys
from ctypes import *
lib = cdll.LoadLibrary('testDLL.dll')
lib.testDLL(3)
如果DLL是COM库类型,则可以使用pythonnet。
pip install pythonnet
然后在python代码中,尝试以下操作
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中的类实例化一个对象,并访问其中的方法。