使用 ctypes 的 .dll 中的 python 中的 C++ 函数 - 未找到函数并且访问冲突

Posted

技术标签:

【中文标题】使用 ctypes 的 .dll 中的 python 中的 C++ 函数 - 未找到函数并且访问冲突【英文标题】:C++ function in python from .dll using ctypes - function not found and access violation 【发布时间】:2017-05-26 23:01:44 【问题描述】:

我有一个名为 hello.cpp 的简单 C++ 代码,它具有打印“Hello world”的功能

#include <iostream>

void hello_world();

int main() 
    std::cout << "Start" << std::endl;


void hello_world() 
    std::cout << "Hello world" << std::endl;

我使用以下方法构建 .dll (~1.9mb):

g++ -c hello.cpp
g++ -static -fPIC -o hello.dll hello.o

(尝试在 python 中访问时使用-shared 会给出WinError 126 ... module not found

python代码是:

from ctypes import cdll

lib = cdll.LoadLibrary('hello.dll')
lib.hello_world()

这会引发以下错误:

AttributeError: function 'hello_world' not found

我读到有人提到__declspec(dllexport) 包装器是必要的,extern "C" 也是如此,这样代码才不会“损坏”。所以现在使用它作为代码:

#include <iostream>

extern "C" 
    __declspec(dllexport) void hello_world();


int main() 
    std::cout << "Opened" << std::endl;



void hello_world() 
    std::cout << "hello world" << std::endl;

python 行 lib.hello_world() 现在引发:

OSError: exception: access violation writing 0x000E28A0

这里有什么问题?如何让 python 识别和运行 .dll 中的 C++ 函数?我可以跳过中间人并以某种方式从 .cpp 文件或 .o 文件运行 C++ 函数吗?

编辑:

使用 eryksun 的答案,事实证明不需要 dllexport。外部“C”是必须的

【问题讨论】:

1:您正在混合 c 编译器和 C (C++) 运行时 (Python 是用 VStudio 编译的,而你的 .dll 是用 g++ 编译的)。 2:您的 .dll 有一个 main 函数,可以将其限定为可执行文件(更不用说缺少 -shared 链接器标志)。 @CristiFati 将我的 C++ 代码中的函数名称从 main 更改为其他任何名称都会在 g++ 进程的第二步时给我一个undefined reference to `WinMain@16' 错误。能否详细说明一下“Python是用VStudio编译的”? 这通常是因为您正在构建一个 Windows 应用程序(检查 [MSDN]: /SUBSYSTEM (Specify Subsystem) 链接器标志)。 在这种情况下我应该构建 Windows 应用程序吗?我不知道 .o 或 .dll 被视为应用程序。如果是或者即使不是,我应该用 g++ 做什么来代替? 试试-static -shared——听起来很奇怪。 【参考方案1】:

感谢@eryksun,在这种情况下,通过这样的编译解决了这个问题:

g++ -c hello.cpp
g++ -static -shared -o hello.dll hello.o

像这样设置 C++ 代码:

#include <iostream>

int main() 
    std::cout << "Opened" << std::endl;


void hello_world() 
    std::cout << "hello world" << std::endl;


extern "C" 
    void hello_world();

像往常一样从 Python 运行它:

from ctypes import cdll

lib = cdll.LoadLibrary('hello.dll')
lib.hello_world()

【讨论】:

以上是关于使用 ctypes 的 .dll 中的 python 中的 C++ 函数 - 未找到函数并且访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

通过 ctypes 使用扩展 dll 中的类需要帮助

在 python 中的 byref 向量参数上使用 ctypes 进行 DLL 转换

使用 ctypes 的 .dll 中的 python 中的 C++ 函数 - 未找到函数并且访问冲突

蟒蛇 |使用 ctypes 访问 dll

如何使用 ctypes 调用具有双下划线函数名的 DLL 函数?

使用 Python ctypes 访问 Visual Foxpro COM DLL