从Python调用C ++ DLL

时间:2014-01-17 11:32:04

标签: python c++ dll mfc ctypes

我使用过MFC的C ++ dll,我想从python中调用它。 此dll在.h文件中包含此标头

LONG CommOpen(BYTE port, LONG baud_rate);

然后我在自由软件dllexp中看到我的函数被调用了?CommOpen @ CFIPcmd @@ QAEJEJ @ Z在二进制文件中所以当我在python中没有报告错误

import ctypes

lib = ctypes.WinDLL('C:\\Users\\toto\\FIProtocol.dll')
prototype = WINFUNCTYPE(c_long, c_byte, c_long)
testPt = ctypes.WINFUNCTYPE (prototype) 
testApi = testPt (("?CommOpen@CFIPcmd@@QAEJEJ@Z", lib))

直到它似乎工作,但我想在Python中调用相当于

的C ++
Long l= CommOpen(5 ,115200);

但我没有发现如何继续。 任何帮助都会非常感激!!

2 个答案:

答案 0 :(得分:4)

鉴于问题中提供的信息,解决方案是:

import ctypes

lib = ctypes.CDLL(r'C:\Users\toto\FIProtocol.dll')
CommOpen = getattr(lib, "?CommOpen@CFIPcmd@@QAEJEJ@Z")
CommOpen.argtypes = [c_byte, c_long]
CommOpen.restype = c_long

现在可以打电话了:

l = CommOpen(5 ,115200)

一些注意事项:

  1. 使用CDLL而不是WinDLL,因为该函数使用默认的cdecl调用约定。
  2. 使用getattr可以指定损坏的名称。
  3. 明确指定argtypesrestype总是值得的。

  4. 然而,事实证明你有一个更大的问题。以上是基于您的函数是非成员函数。考虑到ctypes要求函数是非成员函数或静态函数,这是一个合理的假设。

    但是,当我将托管函数名称放入一个解映射器(例如http://pear.warosu.org/c++filtjs/)时,似乎该函数实际上是这样的:

    public: long __thiscall CFIPcmd::CommOpen(unsigned char,long)
    

    这是C ++对象的成员函数。无法从ctypes访问。您需要创建一个普通的C风格包装器,或者找到一种不同的互操作方法。

答案 1 :(得分:0)

根据http://docs.python.org/2/library/ctypes.html#calling-functions“你可以调用这些函数,就像任何其他Python可调用一样。”我建议运行一个交互式Python控制台(如ipython)并自行检查。

好吧,我刚刚将Python安装到VirtualBox Win32并检查了示例:

>>> from ctypes import *
>>> f = getattr(cdll.msvcrt, "??2@YAPAXI@Z")
>>> f
<_FuncPtr object at 0x00B7EDC8>
>>> f()
24969248
>>> _

所以,是的,您可以像python环境中的任何其他函数一样调用这些函数对象。正如文件所声称的那样:)

同样_cputws有效:

>>> cputws = getattr(cdll.msvcrt, "_cputws")
>>> r = cputws("Hello, World!\n")
Hello, World!
>>> r
0
>>>