2010-09-09 93 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