【问题标题】:Can Python call C++ DLL libraries compiled using extern "C" with ctypes?Python可以调用使用带有ctypes的extern“C”编译的C++ DLL库吗?
【发布时间】:2020-12-20 14:53:48
【问题描述】:

网上有很多文章说Python不能使用ctypes访问C++编译的DLL,还有一些自相矛盾的文章说只要有DLL就可以访问DLL使用 extern "C" 方法编译。所以我只想澄清一下。如果使用 extern "C" 可以吗?

【问题讨论】:

  • 是的,当然。它们看起来与 C DLL 相同
  • 我已经在 LINUX 平台上使用以下信息:nesi.github.io/perf-training/python-scatter/ctypes。我从未在 Windows 平台上尝试过。
  • Python 无法使用 ctypes 访问 C++ 编译的 DLL -- 这不是真的,因为我维护的开源产品(一个 C++ 编译的 DLL)可以使用 python 轻松访问。
  • 当然,比如这个答案:stackoverflow.com/a/62528026/235698

标签: python c++ dll ctypes


【解决方案1】:

有 C++ 编译的 dll 可以与 ctypes 一起使用,而 C++ 编译的 dll 不能直接与 ctypes 一起使用。

如果 API 仅公开 plain-old-data(例如 intint *char * 等)并被包裹在 extern "C" 中,则可以从 ctypes 使用它。

如果在接口中使用非 POD 类(例如 std::vectorstd::string)或 API 未包装在 extern "C" 中,则 dll 不能与 ctypes 一起使用(至少在便携的方式,事不宜迟)。


为什么需要extern "C"

以下声明在 C++ 中有效,但在 C 中无效:

void my_fun(int a);
void my_fun(double a);

因为 C 不执行名称修改,所以这两个函数都将映射到生成的目标文件中名为 my_fun 的符号,这是有问题的。

C++ 会创建两个名称不同的符号,例如 gcc 会创建符号 Z6my_funi_Z6my_fund。 MSVC 有另一种命名方案 - 因此 dll(或共享对象)中的结果符号取决于构建它的编译器。

ctypes 的帮助下,在 dll 中找到这些符号并非不可能 - 它只是不像 C 名称那样简单,因为需要额外的信息 - 使用哪个编译器构建 dll。

C 名称与 ctypes 一起使用,将声明包装到 extern "C" 中会关闭名称修改,因此

extern "C" {
  void my_fun(int a);
  void my_fun(double a);
}

将不再编译,因为编译器将确保一个符号没有多个定义。

为什么不能在接口中使用更复杂的 C++ 类?

extern "C" 不禁止使用std::vector<> 和其他 C++ 类:

extern "C" {
  void my_fun(std::vector<double> a);
}

编译,它只在生成的目标文件中生成符号my_func 而不是?my_fun@@YANV?$vector@NV?$allocator@N@std@@@std@@@Z(使用MSVC)或_Z6my_funSt6vectorIdSaIdEE(使用gcc)。

对于 POD,比如说double[10],内存布局很清晰,例如内存布局。 std::vector 依赖于实现,ctypes 不知道。另一个问题是 - ctypes 无法处理的问题 - 构造函数/析构函数可能比简单的 POD 初始化更复杂。

因此my_fun(std::vector&lt;double&gt;) 的功能不能与ctypes 一起使用。但是,如果知道类的内存布局,可以用ctypes 模拟它们,通过调用 (right) 构造函数来初始化对象(顺便说一句。类方法的符号总是被破坏,即使包装在extern "C" ),调用函数my_fun,然后调用(右)析构函数销毁对象。

【讨论】:

  • 那么,std::vector 和 std::string 等是唯一与 ctypes 不兼容的类吗?
  • @RobertTattorn 反过来说:只有 POD 兼容,其他没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
  • 2019-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
相关资源
最近更新 更多