All, I found a piece of information on how to call c files in python, in these examples: there is a c file, which includes many other header files, the very beginning of this c files is #include Python.h
, then I found that #include Python.h
actually involves many many other header files, such as pystate.h
, object.h
, etc, so I include all the required header files. In an cpp IDE environment, it did not show errors. What I am trying to do is call this c code in python, so from ctypes import *
, then it seems that a dll
should be generated by code such as: cl -LD test.c -test.dll
, but how to use the cl
in this case? I used the cygwin: gcc
, it worked fine. Could anyone help me with this i.e.: Call the C in python? Do I make myself clear? Thank you in advance!!
Well, Now I feel it important to tell me what I did:
The ultimate goal I wanna achieve is:
I am lazy, I do not want to re-write those c codes in python, (which is very complicated for me in some cases), so I just want to generate dll
files that python could call. I followed an example given by googleing "python call c", there are two versions in this examples: linux and windows:
The example test.c
:
#include <windows.h>
BOOL APIENTRY
DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) {
return TRUE;
}
__declspec(dllexport) int
multiply(int num1, int num2) {
return num1 * num2;
}
Two versions: 1, Complie under linux
gcc -c -fPIC test.c
gcc -shared test.o -o test.so
I did this in cygwin on my vista system, it works fine; :)
2, Compile under windows:
cl -LD test.c -test.dll
I used the cl in windows command line prompt, it won't work!
These are the python codes:
from ctypes import *
import os
libtest = cdll.LoadLibrary(os.getcwd() + '/test.so')
print test.multiply(2, 2)
Could anyone try this and tell me what you get? thank you!
You will find the command line options of Microsoft's C++ compiler here.
Consider the following switches for cl:
/nologo /GS /fp:precise /Zc:forScope /Gd
...and link your file using
/NOLOGO /OUT:"your.dll" /DLL <your lib files> /SUBSYSTEM:WINDOWS /MACHINE:X86 /DYNAMICBASE
Please have a look at what those options mean in detail, I just listed common ones. You should be aware of their effect nonetheless, so try to avoid copy&paste and make sure it's really what you need - the documentation linked above will help you. This is just a setup I use more or less often.
Be advised that you can always open Visual Studio, configure build options, and copy the command line invokations from the project configuration dialog.
Edit: Ok, here is some more advice, given the new information you've edited into your original question. I took the example code of your simple DLL and pasted it into a source file, and made two changes:
#include <windows.h>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}
extern "C" __declspec(dllexport) int __stdcall multiply(int num1, int num2)
{
return num1 * num2;
}
First of all, I usually expect functions exported from a DLL to use stdcall calling convention, just because it's a common thing in Windows and there are languages who inherently cannot cope with cdecl, seeing as they only know stdcall. So that's one change I made.
Second, to make exports more friendly, I specified extern "C" to get rid of name mangling. I then proceeded to compile the code from the command line like this:
cl /nologo /GS /Zc:forScope /Gd c.cpp /link /OUT:"foobar.dll" /DL kernel32.lib /SUBSYSTEM:WINDOWS /MACHINE:X86
If you use the DUMPBIN tool from the Visual Studio toolset, you can check your DLL for exports:
dumpbin /EXPORTS foobar.dll
Seeing something like this...
ordinal hint RVA name
1 0 00001010 ?multiply@@YGHHH@Z
...you can notice the exported name got mangled. You'll usually want clear names for exports, so either use a DEF file to specify exports in more details, or the shortcut from above.
Afterwards, I end up with a DLL that I can load into Python like this:
In [1]: import ctypes
In [2]: dll = ctypes.windll.LoadLibrary("foobar.dll")
In [3]: dll.multiply
Out[3]: <_FuncPtr object at 0x0928BEF3>
In [4]: dll.multiply(5, 5)
Out[4]: 25
Note that I'm using ctypes.windll here, which implies stdcall.