开发者

How to use the cl command?

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, Co开发者_Python百科mpile 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜