如何启用pyd在外部C++ dll中调用函数?

问题描述:

我想为我的python程序设计一个外部的DLL。现在我可以使用 C++ Visual Studio 2010生成一个后缀为".pyd"的文件。如果.pyd未与其他由C++生成的.dll文件相关联,则此python库可以正常工作。如何启用pyd在外部C++ dll中调用函数?

不过,现在我需要设计一个.pyd文件,这样的结构调查:

A.pyd -> 1.dll -> 2.dll

在这些文件1,2是C库。生产A.pyd时会调用这些库中的函数。

尽管这个.pyd文件可以通过 VS 2010没有错误地生成,但它无法在Python 3.6中工作。错误报告如下:

Traceback (most recent call last): File "<stdin>”,1号线,在<module> 导入错误:DLL加载失败,无法找到目标程序

即使提到1.dll2.dll存储在的。包含A.pyd同一文件夹中,这个错误依然存在。我不知道我怎么可能让蟒蛇-C++库调用函数的基础上C这些动态链接库。

行!现在我找到了执行此操作的正确方法!

包裹DLL

首先,如果DLL (我称之为dll-A,你需要调用没有出口任何功能(你可以使用dumpbin在VS命令检查导出的函数)你需要包装原来的dll-A。使用隐式调用来包含dll-A。如果在原来的.h /的.lib声明的函数,就像这样:

int func(int a, int b); 

然后,你需要通过这个来创建一个新的dll项目和包装上面的功能:

.H

extern "C" _declspec(dllexport) int w_func(int a, int b); 

的.cpp

int w_func(int a, int b){ 
    return func(a, b); 
} 

当然,如果dumpbin表明dll-A有可用的导出函数,你可以跳过这一步。

出口这个dll (我称之为dll-B,你会得到 'DLL-B' 和它的依赖文件(包括根据文件dll-Adll-A的)之后。

写的。pyd文件

使用显式调用来引用dll-B。使用这种方法时,不应该包含任何lib/.h文件,因为dll-B本身可以为您提供足够的接口。您可以通过此方法加载DLL:

.H

typedef int (*func_ptr)(int a, int b); 

的.cpp(名为Testdll当你写的.pyd项目功能的一部分)

func_ptr FUNC_API = NULL; 
HINSTANCE h = LoadLibraryA("libdll/dllB.dll"); 
//Certainly! you could set the folder of stored dlls! 
if (h){ 
    FUNC_API = (func_ptr)GetProcAddress(h, "w_func"); 
    //You could load more functions here. 
} 
else{ // If the dll could not be found 
    FreeLibrary(h); 
    return 0x100; 
} 
int errorflag=0; 
if (FUNC_API==NULL){ //Check whether the function is valid. 
    cout << "Could not find: func" << endl; 
    errorflag = errorflag | 0x001; 
} 
//You could check more functions here. 
if (errorflag!=0){ // if any function could not be found. 
    FreeLibrary(h); 
    return 0x100 | errorflag; 
} 
//process functions. 
int a,b,c; 
c = FUNC_API(a,b); 
//Free the lib 
if (h) 
    FreeLibrary(h); 

建立自己的后.pyd,你可以得到你的python数据库(我称之为pyd-C

链接与Python

在Python项目的.pyd,你可以用这种方法测试这个文件:

的.py

import pydC 

if __name__ == '__main__': 
    X = pydC.cclass() 
    X.Testdll(); 

然后你就可以发现,功能表现不错。

注意到你的.pyd应该放在与.py相同的文件夹中。因为您在libdll/dllB.dll中设置了dll-B,所以应将dll-B放在名为libdll的文件夹中。但是,因为dll-B隐含地调用dll-A和其他依赖的dll,所以dll-A和其他文件应位于工作空间文件夹中,即与.py相同的文件夹。

总之,你需要进入工作区文件夹,该文件夹的形成是如下:

./ 
    Test.py 
    pydC.pyd 
    dllA.dll 
    dllA_depended1.dll 
    ... 
    libdll/ 
     dllB.dll 
+0

如果您有任何refered的dll写的不好,你可能会遇到严重的错误!这很不幸,因为你可能无法完善那些依赖于dll的东西。通常,您可以编写一个C程序来明确引用导出的dll以测试是否可以运行这些dll。如果.exe引发错误,那么在.py中遇到同样的错误几乎是不可避免的。 –