【问题标题】:Loading C++ class in Python在 Python 中加载 C++ 类
【发布时间】:2019-03-05 05:13:34
【问题描述】:

我正在尝试在 Python 中导入 C++ 类。 我知道我可以使用 BoostPython、SWIG 或 Cython,但出于教学目的,我尝试使用 extern "C" 手动导出 C++ 方法和函数。简而言之,我正在尝试复制this

我的环境是 Windows 10,带有 Anaconda 3 和 Python 3.6。我已经安装了 mingw64 4.8.3 作为 C/C++ 编译器。

这是我的foo.cpp

#include <iostream>
// A simple class with a constuctor and some methods...
class Foo
{
    public:
        Foo(int);
        void bar();
        int foobar(int);
    private:
        int val;
};
Foo::Foo(int n)
{
    val = n;
}
void Foo::bar()
{
    std::cout << "Value is " << val << std::endl;
}
int Foo::foobar(int n)
{
    return val + n;
}
// Define C functions for the C++ class - as ctypes can only talk to C...
extern "C"
{
    Foo* Foo_new(int n) {return new Foo(n);}
    void Foo_bar(Foo* foo) {foo->bar();}
    int Foo_foobar(Foo* foo, int n) {return foo->foobar(n);}
}

我是这样编译的:g++ -c -fPIC foo.cpp -o foo.o。 输出是:

foo.cpp:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
#include <iostream>
^

然后,我以这种方式编译:g++ -shared -Wl,-soname,libfoo.dll -o libfoo.dll foo.o 没有错误/警告。文件夹中出现了文件libfoo.dll

当我在 Python 中尝试时:

import ctypes
lib = ctypes.windll.LoadLibrary('libfoo.dll')

我收到错误 OSError: [WinError 126] the specified module could not be found。我的 Python 工作目录是 libfoo.dll 文件夹。

我尝试创建一个简单的 C-HelloWorld 库:我以相同的方式编译(一部分 gcc 而不是 g++),并成功将其加载到 Python 中。

问题出在哪里?它在编译说明中吗?还是在代码中?

【问题讨论】:

  • 你有没有试过给它一个.dll的绝对路径?这样做时,请记住转义斜线:C:\\...\\...\\libfoo.dll
  • 是的,我试过了。另外,我尝试将它移动到不同的磁盘(从E:\\...\\libfoo.dllC:\\...\\libfoo.dll
  • 我不确定 mingw g++。在 VS 中,创建函数 extern 对于 DLL 来说是不够的。如果我想从其他 EXE/DLL 中使用它们,我必须将它们导出。出于好奇,我在谷歌上搜索并发现了这个:HOWTO Create and Deploy a Sample DLL using MinGW 和这个Exporting a class from a DLL for multiple instantiations。看来mingw也是一样。

标签: python c++ dll


【解决方案1】:

我从@Scheff 评论开始找到了解决方案。

在 Linux 上(我在 Ubuntu 16、GCC 4.4.0 和 Python 3.6 上尝试过),我的问题代码无需修改即可正常运行(代码和编译说明都如此)。

在 Windows 上,我以这种方式修改了 extern "C" 块:

extern "C"
{
     __declspec(dllexport) Foo* Foo_new(int n) {return new Foo(n);}
     __declspec(dllexport) void Foo_bar(Foo* foo) {foo->bar();}
     __declspec(dllexport) int Foo_foobar(Foo* foo, int n) {return foo->foobar(n);}
}

我像以前一样重新编译。

此后,我能够按照question link 中的说明导入模块和 C++ 类。

C++打印功能的实现请看this question

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-08
    • 1970-01-01
    相关资源
    最近更新 更多