使用 Python 从 C/C++ DLL 调用方法
Posted
技术标签:
【中文标题】使用 Python 从 C/C++ DLL 调用方法【英文标题】:Calling methods from C/C++ DLL with Python 【发布时间】:2016-08-17 13:20:57 【问题描述】:我这里有一个关于从 c/c++ dll 调用函数的教程,示例是从official tutorial 编写的。
WINUSERAPI int WINAPI
MessageBoxA(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType);
Here is the wrapping with ctypes:
>>>
>>> from ctypes import c_int, WINFUNCTYPE, windll
>>> from ctypes.wintypes import HWND, LPCSTR, UINT
>>> prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, UINT)
>>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", None), (1, "flags", 0)
>>> MessageBox = prototype(("MessageBoxA", windll.user32), paramflags)
>>>
The MessageBox foreign function can now be called in these ways:
>>>
>>> MessageBox()
>>> MessageBox(text="Spam, spam, spam")
>>> MessageBox(flags=2, text="foo bar")
>>>
A second example demonstrates output parameters. The win32 GetWindowRect function retrieves the dimensions of a specified window by copying them into RECT structure that the caller has to supply. Here is the C declaration:
WINUSERAPI BOOL WINAPI
GetWindowRect(
HWND hWnd,
LPRECT lpRect);
Here is the wrapping with ctypes:
>>>
>>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError
>>> from ctypes.wintypes import BOOL, HWND, RECT
>>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
>>> paramflags = (1, "hwnd"), (2, "lprect")
>>> GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
>>>
这个例子在函数是外部的时候有效,但是,假设我有一个对象的引用,我想用参数从那个对象调用一个函数,我该怎么做?
我确实从 'dumpbin -exports' 中看到了所有函数签名的日志,我尝试使用函数的全名,但它仍然不起作用。
任何其他想法都会受到祝福。
【问题讨论】:
你怎么知道它不起作用? 我尝试以与教程相同的方式激活它,只是将名称替换为导出中的签名,但我仍然收到来自 python 日志的错误,说它无法调用该函数, 'tuple' 的东西...我不在同一台计算机上工作,我正在输入它,所以这一切都来自记忆,如果您需要任何特定数据,请告诉我 我认为我们需要详细信息;我们正在这里进行故障排除。 Extending Python with C/C++的可能重复 我看到了一个叫 SWIG 的工具,它可以做我需要的吗?从对象引用中调用方法 【参考方案1】:不幸的是,您无法使用 ctypes
轻松且便携地做到这一点。
ctypes
旨在调用具有 C 兼容数据 类型的 DLL 中的函数。
由于 C++ 没有standard binary interface,您应该知道生成 DLL 的编译器是如何生成代码的(即类布局...)。
更好的解决方案是创建一个新的 DLL,它使用当前的 DLL 并将方法包装为纯 c 函数。请参阅boost.python 或SWIG 了解更多详情。
【讨论】:
在DLL中调用方法有什么解决办法吗? 您可以使用普通的 c 函数调用来包装方法调用或使用答案中的工具。 想到了那个.. 我还看到了一个叫 SWIG 的工具,它可以做我需要的吗?从对象引用中调用方法 与ctypes
不同,它加载 DLL 并在运行时调用其函数 - 使用这些工具,您可以创建一个包装方法的新 DLL。您将能够使用来自 python 的新 DLL。以上是关于使用 Python 从 C/C++ DLL 调用方法的主要内容,如果未能解决你的问题,请参考以下文章