Modern/2020 从 Python 调用 C++ 代码的方法

7 c++ python

我正在尝试从 Python 脚本调用 C++ 函数。从 2010 年到 2015 年,我在 Stackoverflow 上看到了不同的解决方案,但它们都使用复杂的包,并希望有更简单/更新和更复杂的东西。我试图调用的 C++ 函数接受一个双变量并返回一个双变量。

double foo(double var1){
    double result = ...
    return result;
}
Run Code Online (Sandbox Code Playgroud)

Ton*_*ous 13

Python 有ctypes包,它允许调用 DLL 或共享库中的函数。将 C++ 项目编译到 Linux 上的共享库 (.so) 或Windows 上的DLL。导出您希望对外公开的功能。

C++ 支持函数重载,为了避免二进制代码中的歧义,在函数名称中添加了附加信息,称为name mangling。而在 C 中,函数名称保持不变,为确保名称未更改,只需将其放置在 extern “C” 块中即可。


演示:在这个虚拟演示中,我们的库只有一个函数,获取一个 int 并打印它。

库文件

#include <iostream>

int Function(int num) 
{
    std::cout << "Num = " << num << std::endl;
    return 0;
}

extern "C" {
    int My_Function(int a)
    {
        return Function(a);
    }
}
Run Code Online (Sandbox Code Playgroud)

我们将首先将其编译为共享对象

g++ -fPIC -shared -o libTest.so lib.cpp
Run Code Online (Sandbox Code Playgroud)

现在我们将使用 ctypes 来加载共享对象/dll 和函数。

我的库文件

import ctypes
import sys
import os 

dir_path = os.path.dirname(os.path.realpath(__file__))
handle = ctypes.CDLL(dir_path + "/libTest.so")     

handle.My_Function.argtypes = [ctypes.c_int] 
  
def My_Function(num):
    return handle.My_Function(num)    
Run Code Online (Sandbox Code Playgroud)

对于我们的测试,我们将调用函数 num = 16

测试文件

from myLib import *

My_Function(16)
Run Code Online (Sandbox Code Playgroud)

预期的出来也是如此。

在此处输入图片说明

  • @阿德里安B。`My_Function()` 位于“extern C”中,以防止名称损坏,因此当有人搜索符号(函数名称)时,他们会找到它。一切都暴露在外面。要限制公开的内容,您可以使用 [-fvisibility=hidden](/sf/ask/249924881/) 进行编译,然后标记要公开的函数使用 `__attribute__((visibility("default")))` 如[此答案](/sf/answers/249930131/)。任何提供加载“.dll”或“.so”的编程语言都可以。 (2认同)
  • @阿德里安B。extern C **不**用于公开,或允许使用这个唯一的函数!这是确保函数名称在导出的符号中保持不变的方法!这样任何尝试使用它(即搜索函数名称)的人(在 python 中)都会在“.so/.dll”中找到它。所以将它们放在“extern C”中非常重要 (2认同)