从 Python 调用的 C++ dll

2022-01-12 00:00:00 python dll ctypes c++ mfc

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

I have used a C++ dll using MFC and I would like to call it from python. This dll contains this header in the .h file

LONG CommOpen(BYTE port, LONG baud_rate);

然后我在免费软件 dllexp 中看到我的函数在二进制文件中被称为 ?CommOpen@CFIPcmd@@QAEJEJ@Z 所以我在 python 中执行时不会报告错误

Then I see in the free software dllexp that my function is called ?CommOpen@CFIPcmd@@QAEJEJ@Z in the binary file so no error is reported when I do in 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++ 中的等价物

Until there it seems to work but then I would like to call the in Python the equivalent in C++ of

Long l= CommOpen(5 ,115200);

但我不知道如何进行.任何帮助将不胜感激!

But I Didn't find know how to proceed. Any help would be really appreciated!!

推荐答案

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

Given the information presented in the question, the solution is:

import ctypes

lib = ctypes.CDLL(r'C:Users	otoFIProtocol.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 总是值得的.
  1. Use CDLL rather than WinDLL because the function used the default cdecl calling convention.
  2. Use getattr to be able to specify the mangled name.
  3. It always pays to specify argtypes and restype explicitly.

<小时>

然而,你发现你有一个更大的问题.以上是在您的函数是非成员函数的基础上编写的.这是一个合理的假设,因为 ctypes 要求函数要么是非成员的,要么是静态的.


However, it transpires that you have a much greater problem. The above was written on the basis that your function is a non-member function. Which is a reasonable assumption given that ctypes requires functions to be either non-member, or static.

但是,当我将您的托管函数名称放入 demanger 时(例如 http://pear.warosu.org/c++filtjs/) 看来函数其实是:

However, when I put your managed function name into a demanger (for instance http://pear.warosu.org/c++filtjs/) it seems that the function is in fact:

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

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

That is a member function of a C++ object. That cannot be accessed from ctypes. You'll need to create a plain C style wrapper, or find a different method of interop.

相关文章