python-3.x - 是否可以使用 C++Builder 和 CMake 创建 Python 模块?

标签 python-3.x swig c++builder dllimport dllexport

C++Builder 的 32 位编译器 bcc32 默认情况下使用 cdecl 调用约定创建共享库,并在导出函数前添加下划线前缀, 例如'_函数名称'。另一方面,Visual Studio 不为导出函数添加前缀。

Python 在导入 pyd 模块时需要一个名为 PyInitialize_modulename 的函数。由于 bcc32 在此函数前面添加了下划线,将其渲染为 _PyInitialize_modulename,Python 将无法导入 bcc32 创建的模块。

使用 CMake,有谁知道如何在编译/创建 pyd 模块时添加模块定义文件 .def 以将带前缀的函数别名为“无前缀”函数?

更新。回应下面 Lebeau 先生的回答(作为评论); 这个问题不是关于 CType 的,而是关于 SWIG 的。 CTypes 允许以简单的方式包装 C/C++ DLL,但主要处理 C 结构和 POD 数据。

另一方面,Swig 允许客户端在 Python 中获取面向对象的对象,类似于从 C++ DLL 导出的对象。 Swig 可以在处理 C++ header 时执行此操作。

Swig 确实创建了一个 C++ 文件,该文件被编译为 .pyd 文件(本质上是一个 DLL,如前所述)。 Python 在尝试将其作为模块加载时查找的第一个导出函数是 Pyinit_MyModule (Python 3)。如前所述,使用 C++ Builder 时,此函数将导出为 _Pyinit_MyModule。问题是 Swig 导出了这个函数,而我作为 Swig 的客户端无法更改这个函数的调用约定(据我所知)。

我相信我最初认为Python需要__stdcall来实现这个函数是错误的,因为VS默认使用cdecl,但没有添加'_',而且它工作得很好。

但是,设置编译器标志来抑制下划线也不起作用,因为 Python 导入库中的某些函数会变得不可见,并成为无法解析的外部函数。所以也许这个问题比乍看起来更复杂。但我想这与调用约定无关。

最佳答案

cdecl 只是每个 C++ 编译器使用的典型默认调用约定。如果您想使用 stdcall 来代替,您当然可以这样做(Python 期望使用 stdcall 是有道理的,因为 Win32 API 使用的就是这个)。

在模块的 C++ 代码中,您可以在导出的函数声明中显式使用 __stdcall

或者,您可以在 C++Builder 的项目设置中更改默认调用约定,然后在函数声明中省略任何调用约定。

现在,回答您的问题 - 在导入 pyd 模块时,如果该模块使用 cdecl,请使用 ctypes.cdll 调用其函数。如果模块使用 stdcall,请改用 ctypes.windll。 Python 文档对此进行了介绍:

https://docs.python.org/3/library/ctypes.html#loading-dynamic-link-libraries

16.16.1.1. Loading dynamic link libraries

ctypes exports the cdll, and on Windows windll and oledll objects, for loading dynamic link libraries.

You load libraries by accessing them as attributes of these objects. cdll loads libraries which export functions using the standard cdecl calling convention, while windll libraries call functions using the stdcall calling convention. oledll also uses the stdcall calling convention, and assumes the functions return a Windows HRESULT error code. The error code is used to automatically raise an OSError exception when the function call fails.

https://docs.python.org/3/faq/windows.html#is-a-pyd-file-the-same-as-a-dll

Is a *.pyd file the same as a DLL?

Yes, .pyd files are dll’s, but there are a few differences. If you have a DLL named foo.pyd, then it must have a function PyInit_foo(). You can then write Python “import foo”, and Python will search for foo.pyd (as well as foo.py, foo.pyc) and if it finds it, will attempt to call PyInit_foo() to initialize it. You do not link your .exe with foo.lib, as that would cause Windows to require the DLL to be present.

关于python-3.x - 是否可以使用 C++Builder 和 CMake 创建 Python 模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49909832/

相关文章:

django - 在 Ubuntu 上使用 virtualenv 为 python3 设置虚拟环境

python - 如何在 Tkinter 中高效创建大型条目网格?

python-3.x - docker 运行错误:DPI-1047:无法找到64位Oracle客户端库

python - 如何将 SwigPyObject 转换为 ctypes void*

python - 如何使用不同的标记分隔符连接多个 Pandas DataFrame 列?

node.js - CMake 错误 : Could NOT find SWIG (missing: SWIG_DIR)

c++ - 在 Eclipse 中调试混合的 Python/C++ 代码

c++builder - borland c++ builder如何用包制作exe文件

delphi - 处理 Windows 10 上 DPI(文本大小)的运行时更改

c++ - 工作线程中的 GDI 打印机设备上下文随机失败