I'm trying to design an external DLL
for my python program. Now I could use the C++ and Visual Studio 2010 to produce a file with a postfix of ".pyd"
. If the .pyd
is not attached with other .dll
files produced by C++, this python library could work well.
However, now I need to design a .pyd
file with such a struction:
A.pyd -> 1.dll
-> 2.dll
in which the files 1,2 are C libraries. The functions in these libraries are called when producing A.pyd
.
Although this .pyd
file could be produced without errors by VS 2010, it could not work in python 3.6. The error report is as follow:
Traceback (most recent call last):
File "
<stdin>
", line 1, in <module>
ImportError: DLL load failed, could not find the target program.
Even when the referred 1.dll
and 2.dll
are stored in the same folder that contains A.pyd
, this error still exists. I wonder how could I enable the python-C++ library to call the functions in these dynamic link libraries based on C
.
OK! Now I have found the correct way to perform this operation!
At first, if the dll (I call it dll-A
) that you need to call has not exported any function (you could use dumpbin
in VS command to check the exported functions), you need to wrap the original dll-A
. Use the implicit call to include dll-A
. If there is a function declared in the original .h/.lib, like this:
int func(int a, int b);
Then you need to create a new dll project and wrap the above function by this:
.h
extern "C" _declspec(dllexport) int w_func(int a, int b);
.cpp
int w_func(int a, int b){
return func(a, b);
}
Certainly, if the dumpbin
shows that dll-A
have avaliable exported functions, you could skip this step.
After exporting this dll (I call it dll-B
), you will get 'dll-B' and its depending files (including dll-A
and dll-A
's depending files).
Use the explicit call to refer dll-B
. When using this method, you should not include any lib/.h files, because dll-B
itself could provide you with enough interfaces. You could load the dll by this method:
.h
typedef int (*func_ptr)(int a, int b);
.cpp (part of a function named Testdll
when you write the .pyd project)
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);
After build your own .pyd, you could get your python database (I call it pyd-C
).
In python project, you could test this file by this method:
.py
import pydC
if __name__ == '__main__':
X = pydC.cclass()
X.Testdll();
Then you can find that the function is performed well.
Noted that your .pyd should be in the same folder with where .py is. Because you have set dll-B
in libdll/dllB.dll
, dll-B
should be put in the folder named libdll
. However, because dll-B
calls dll-A
and other depending dlls implicitly, dll-A
and other files should be in your workspace folder, i.e. the same folder with where .py is.
In short, you need to enter the workspace folder, and the folder formation is as follow:
./
Test.py
pydC.pyd
dllA.dll
dllA_depended1.dll
...
libdll/
dllB.dll