2010-09-09 89 views
1

所有,我发现了一条关于如何在python中调用c文件的信息,在这些例子中:有ac文件,其中包含许多其他头文件,这个c文件的最开始部分是#include Python.h,然后我发现#include Python.h实际上涉及许多其他头文件,如pystate.h,object.h等,所以我包含了所有需要的头文件。在一个cpp IDE环境中,它没有显示错误。 我想要做的是在python中调用这个c代码,所以from ctypes import *,那么看起来dll应该由代码生成,例如:cl -LD test.c -test.dll,但是在这种情况下如何使用cl?我使用了cygwin:gcc,它工作正常。任何人都可以帮我解决这个问题,例如:在python中调用C?我是否清楚自己?先谢谢你!!如何使用cl命令?

嗯,现在我觉得告诉我我做了什么很重要: 我想达到的最终目标是:我很懒,我不想在python中重写那些c代码,在某些情况下对我来说很复杂),所以我只想生成python可以调用的文件dll 。我接着googleing “蟒蛇调用C” 给出的,有两个版本在这个实例的实例:test.c 的例子:Linux和Windows

#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; 
} 

两个版本: 1,Complie linux下

gcc -c -fPIC test.c 
gcc -shared test.o -o test.so 

我在我的vista系统上使用了cygwin,它工作的很好; :)

2,编译Windows下:

cl -LD test.c -test.dll 

我以前在Windows命令行提示符下CL,它不会工作!

这些蟒蛇代码:

from ctypes import * 
import os 
libtest = cdll.LoadLibrary(os.getcwd() + '/test.so') 
print test.multiply(2, 2) 

任何人都可以试试这个,告诉我你得到了什么?谢谢!

+0

这实际上与Python没有任何关系,只是询问如何在命令行上运行Microsoft工具链的编译器。请考虑标记你的问题。 – 2010-09-09 18:58:51

+0

@Jim:也许我应该补充:如何从c生成dll文件,以便python可以调用它,就像在windows中一样,IDE给出的烦人的噪声无关代码本身 – serina 2010-09-09 19:04:25

+0

看,也许你真正的问题是与您遇到的“噪音”相关,但您自己已经提出了一种解决方案,即从命令行进行编译。您可能会问,如何配置您的IDE以消除噪音,或者,如果噪音有任何意义。 – 2010-09-09 19:08:40

回答

2

你会发现微软的C++编译器here的命令行选项。

考虑下面的开关,用于CL:

/nologo /GS /fp:precise /Zc:forScope /Gd 

...和链接使用

/NOLOGO /OUT:"your.dll" /DLL <your lib files> /SUBSYSTEM:WINDOWS /MACHINE:X86 /DYNAMICBASE 

请看看什么这些选项的详细意味着你的文件,我刚上市常见的。尽管如此,你应该知道它们的效果,所以尽量避免复制&粘贴,并确保它确实是你需要的 - 上面链接的文档将帮助你。这只是我多次或多次使用的设置。

请注意,您始终可以打开Visual Studio,配置构建选项,并从项目配置对话框复制命令行调用。

编辑: 好的,这里有一些更多的建议,因为你已经编辑了你的原始问题的新信息。我把你的简单的DLL的示例代码并粘贴成一个源文件,并提出了两个转变:

#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; 
} 

首先,我通常期望从一个DLL使用stdcall调用导出的函数,只是因为它的在Windows中是一件常见的事情,并且有些语言本身无法应付cdecl,因为他们只知道stdcall。所以这是我做的一个改变。

二,为了使出口更友好,我指定了extern“C”来摆脱name mangling。我接着编译从这样的命令行代码:

cl /nologo /GS /Zc:forScope /Gd c.cpp /link /OUT:"foobar.dll" /DL kernel32.lib /SUBSYSTEM:WINDOWS /MACHINE:X86 

如果使用从Visual Studio工具集的DUMPBIN工具,您可以检查您的DLL出口:

dumpbin /EXPORTS foobar.dll 

看到的东西像这样...

ordinal hint RVA  name 
    1 0 00001010 [email protected]@[email protected] 

...你可以看到导出的名字得到了错位。您通常需要明确的导出名称,因此可以使用DEF文件更详细地指定导出,或者使用上面的快捷方式。

之后,我结束了一个DLL,我可以加载到Python的是这样的:

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 

请注意,我使用ctypes.windll这里,这意味着STDCALL。

+0

非常感谢你! – serina 2010-09-09 19:12:04

+0

如果你发现我的答案有帮助,你可以自由地点击接受它;) – 2010-09-09 19:29:19

+0

我可以使用cl现在,但它不会工作,gcc工作正常... – serina 2010-09-09 19:46:14