python使用c庫
⑴ 怎樣在python中使用c++的靜態庫
如何讓python調用C和C++代碼 安裝python後,會有一個chm格式的python手冊。要搞明白如何讓python調用C/C++代碼(也就是寫python的 extension),你需要征服手冊中的 厚厚的一章。在昨天花了一個小時看地頭暈腦脹,仍然不知道如何寫python的extensi...
如何讓python調用C和C++代碼
安裝python後,會有一個chm格式的python手冊。要搞明白如何讓python調用C/C++代碼(也就是寫python的 extension),你需要征服手冊中的
<<Extending && embedding>>厚厚的一章。在昨天花了一個小時看地頭暈腦脹,仍然不知道如何寫python的extension後,查閱了一些其他 書籍,最終在<<Python Programming On Win32>>書中找到了教程。
下面記錄一下如何在visual studio 2005中,寫一段C/C++的MessageBox代碼,然後提供後python調用,最後的結果當然是顯示一個MessageBox.
1. 首先要明白的是,所謂的python擴展(也就是你提供給python的c/c++代碼,不一定是c/c++代碼,可以是其他語言寫的代碼)是一個 dll,並且這個dll放在本機python安裝目錄下的DLLs目錄下(譬如我機器上的路徑是:F:\Program Files\Python25\DLLs),假如我們接下來要寫的擴展mole名為mb,python調用的代碼為: import mb
mb.showMsg("Python's really amazing, I kindda love it!")
python怎麼找到我們的mb模塊呢?就是上面說的,我們要生成一個mb.dll,然後拷貝到Dlls目錄下面,為了區別普通的dll和python專用擴展的dll,我們的 mb.dll修改成mb.pyd(python dll)
2. 搭建環境,我們要使用python提供的c頭文件和lib庫來進行擴展的開發。 在vs 2005下點擊菜單 "工具"->"選項", 打開選項對話框,選擇"項目和解決方案->VC++目錄", 然後在右邊"顯示以下內容的目錄"得comboBox上選擇"包含文件」,添加python的include目錄(我的機器上是"F:\Program
Files\Python25\include"),然後選擇庫文件,添加python的libs目錄(我的機器上是"F:\Program Files\Python25\libs")。
既然擴展是一個dll,接下來我們要建立一個「動態鏈接庫」工程,然後開始寫代碼:
#include <python.h> //python.h是包含python一些定義的頭文件,在python的include目錄下 /*
我的python版本是2.5, 因為安裝python後它沒提供debug下的lib庫文件,因此你必須生成release版的dll,
想要生成dll版本的,你要到python官網上自己去下載python源代碼,當然你可以繼續生成release版本的dll,但dll中包含調試信息
⑶ c可以調用python嗎
可以的。
C中內嵌Python
新建立一個工程,首先需要將工作目錄設置到Python-3.1.1PCbuild中,以獲取到動態庫,至於靜態庫的包含,Include目錄的指定,那自然也是少不了的。文件中需要包含Python.h文件,這也是必須的。
介面中
Py_Initialize();
Py_Finalize();
其他的根據需求,再引入相應的python builder 即可
⑷ 怎樣讓Python腳本與C++程序互相調用
二、Python調用C/C++
1、Python調用C動態鏈接庫
Python調用C庫比較簡單,不經過任何封裝打包成so,再使用python的ctypes調用即可。
(1)C語言文件:pycall.c
[html] view plain
/***gcc -o libpycall.so -shared -fPIC pycall.c*/
#include <stdio.h>
#include <stdlib.h>
int foo(int a, int b)
{
printf("you input %d and %d\n", a, b);
return a+b;
}
(2)gcc編譯生成動態庫libpycall.so:gcc -o libpycall.so -shared -fPIC pycall.c。使用g++編譯生成C動態庫的代碼中的函數或者方法時,需要使用extern "C"來進行編譯。
(3)Python調用動態庫的文件:pycall.py
[html] view plain
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libpycall.so")
lib.foo(1, 3)
print '***finish***'
(4)運行結果:
2、Python調用C++(類)動態鏈接庫
需要extern "C"來輔助,也就是說還是只能調用C函數,不能直接調用方法,但是能解析C++方法。不是用extern "C",構建後的動態鏈接庫沒有這些函數的符號表。
(1)C++類文件:pycallclass.cpp
[html] view plain
#include <iostream>
using namespace std;
class TestLib
{
public:
void display();
void display(int a);
};
void TestLib::display() {
cout<<"First display"<<endl;
}
void TestLib::display(int a) {
cout<<"Second display:"<<a<<endl;
}
extern "C" {
TestLib obj;
void display() {
obj.display();
}
void display_int() {
obj.display(2);
}
}
(2)g++編譯生成動態庫libpycall.so:g++ -o libpycallclass.so -shared -fPIC pycallclass.cpp。
(3)Python調用動態庫的文件:pycallclass.py
[html] view plain
import ctypes
so = ctypes.cdll.LoadLibrary
lib = so("./libpycallclass.so")
print 'display()'
lib.display()
print 'display(100)'
lib.display_int(100)
(4)運行結果:
3、Python調用C/C++可執行程序
(1)C/C++程序:main.cpp
[html] view plain
#include <iostream>
using namespace std;
int test()
{
int a = 10, b = 5;
return a+b;
}
int main()
{
cout<<"---begin---"<<endl;
int num = test();
cout<<"num="<<num<<endl;
cout<<"---end---"<<endl;
}
(2)編譯成二進制可執行文件:g++ -o testmain main.cpp。
(3)Python調用程序:main.py
[html] view plain
import commands
import os
main = "./testmain"
if os.path.exists(main):
rc, out = commands.getstatusoutput(main)
print 'rc = %d, \nout = %s' % (rc, out)
print '*'*10
f = os.popen(main)
data = f.readlines()
f.close()
print data
print '*'*10
os.system(main)
(4)運行結果:
4、擴展Python(C++為Python編寫擴展模塊)
所有能被整合或導入到其它python腳本的代碼,都可以被稱為擴展。可以用Python來寫擴展,也可以用C和C++之類的編譯型的語言來寫擴展。Python在設計之初就考慮到要讓模塊的導入機制足夠抽象。抽象到讓使用模塊的代碼無法了解到模塊的具體實現細節。Python的可擴展性具有的優點:方便為語言增加新功能、具有可定製性、代碼可以實現復用等。
為 Python 創建擴展需要三個主要的步驟:創建應用程序代碼、利用樣板來包裝代碼和編譯與測試。
(1)創建應用程序代碼
[html] view plain
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int fac(int n)
{
if (n < 2) return(1); /* 0! == 1! == 1 */
return (n)*fac(n-1); /* n! == n*(n-1)! */
}
char *reverse(char *s)
{
register char t, /* tmp */
*p = s, /* fwd */
*q = (s + (strlen(s) - 1)); /* bwd */
while (p < q) /* if p < q */
{
t = *p; /* swap & move ptrs */
*p++ = *q;
*q-- = t;
}
return(s);
}
int main()
{
char s[BUFSIZ];
printf("4! == %d\n", fac(4));
printf("8! == %d\n", fac(8));
printf("12! == %d\n", fac(12));
strcpy(s, "abcdef");
printf("reversing 'abcdef', we get '%s'\n", \
reverse(s));
strcpy(s, "madam");
printf("reversing 'madam', we get '%s'\n", \
reverse(s));
return 0;
}
上述代碼中有兩個函數,一個是遞歸求階乘的函數fac();另一個reverse()函數實現了一個簡單的字元串反轉演算法,其主要目的是修改傳入的字元串,使其內容完全反轉,但不需要申請內存後反著復制的方法。
(2)用樣板來包裝代碼
介面的代碼被稱為「樣板」代碼,它是應用程序代碼與Python解釋器之間進行交互所必不可少的一部分。樣板主要分為4步:a、包含Python的頭文件;b、為每個模塊的每一個函數增加一個型如PyObject* Mole_func()的包裝函數;c、為每個模塊增加一個型如PyMethodDef MoleMethods[]的數組;d、增加模塊初始化函數void initMole()。
⑸ 如何在python中使用C的頭文件
最簡單的,
把那個c的程序改成動態鏈接庫。
然後在python裡面用ctypes導進來。
省得你去看Python API了
⑹ python調用c語言動態庫dll/.so中的函數的參數是結構體的問題
java源自C++,C++源自C語言....
各有優點呀,不知道要怎麼回答了,或許樓主是搞C語言的吧,這些語言都各有特點呀...
首先應該清晰,Java是由C++發展而來的,他保留了c++的大部分內容,類似於c++,
但句法更清晰,規模更小,更易學。他是在對多種程式設計語言進行了深入細致研究的
基礎上,據棄了其他語言的不足之處,從根本上解決了c++的固有缺陷,而產生的一種
新的完全方面向對象的語言。
Java和c++的相似之處多於不同之處,但兩種語言問幾處主要的不同使得Java更容易
學習,並且編程環境更為簡單。
因篇幅所限,這里不能完全列出不同之處,僅列出比較顯著的差別:
1.指針
Java無指針,並且增添了自動的內存管理功能,從而有效地防
止了c/c++語言中指針操作失誤,如指針懸空所造成的系統崩潰。
比w操作返回一對象的引用,類似於c++中的引用;在c++中,
new返回一個對象的指針。在Java中無指針,不會遇見下面這樣的
語句:
Mywork?>Mywork();
沒有指針的程式無法訪問不屬於他的內存,消除了在c++
中?些常見的錯誤,這有利於Java程式的安全。
2.多重繼承
c++支持多重繼承,這是c++的一個特徵,他允許多父類派
生一個類。盡管多重繼承功能非常強,但使用復雜,而且會引起許多麻
煩,編譯程式實現他也非常不容易。Java不支持多重繼承,但允許一個
類繼承多個介面(界面),實現了c++多重繼承的功能,又避免了c++的
許多缺陷。
⑺ python 怎麼調用c語言介面
ctypes: 可直接調用c語言動態鏈接庫。
使用步驟:
1> 編譯好自己的動態連接庫
2> 利用ctypes載入動態連接庫
3> 用ctype調用C函數介面時,需要將python變數類型做轉換後才能作為函數參數,轉換原則見下圖:
#Step1:test.c#include<stdio.h>
intadd(inta,intb)
{
returna+b;
}#Step2:編譯動態鏈接庫(如何編譯動態鏈接庫在本文不詳解,網上資料一大堆。)gcc-fPIC-sharedtest.c-olibtest.so
#Step3:test.py
fromctypesimport*mylib=CDLL("libtest.so")或者cdll.LoadLibrary("libtest.so")add=mylib.add
add.argtypes=[c_int,c_int]#參數類型,兩個int(c_int是ctypes類型,見上表)
add.restype=c_int#返回值類型,int(c_int是ctypes類型,見上表)
sum=add(3,6)
⑻ python是用c寫的嗎
python是用c寫的,下面給大家介紹一下Python與c的聯系:
python的誕生
1991年,第一個Python編譯器(同時也是解釋器)誕生。它是用C語言實現的,並能夠調用C庫(.so文件)。從一出生,Python已經具有了:類(class),函數(function),異常處理(exception),包括表(list)和詞典(dictionary)在內的核心數據類型,以及模塊(mole)為基礎的拓展系統。
Guido希望有一種語言,這種語言能夠像C語言那樣,能夠全面調用計算機的功能介面,又可以像shell那樣,可以輕松的編程。ABC語言讓Guido看到希望。ABC是由荷蘭的CWI (Centrum Wiskunde & Informatica, 數學和計算機研究所)開發的。Guido在CWI工作,並參與到ABC語言的開發。ABC語言以教學為目的。與當時的大部分語言不同,ABC語言的目標是「讓用戶感覺更好」。ABC語言希望讓語言變得容易閱讀,容易使用,容易記憶,容易學習,並以此來激發人們學習編程的興趣。
相關推薦:《Python基礎教程》
python與c
Python語法很多來自C,但又受到ABC語言的強烈影響。來自ABC語言的一些規定直到今天還富有爭議,比如強制縮進。但這些語法規定讓Python容易讀。另一方面,Python聰明的選擇服從一些慣例(特別是C語言的慣例)。比如使用等號賦值,使用def來定義函數。Guido認為,如果「常識」上確立的東西,沒有必要過度糾結。
Python從一開始就特別在意可拓展性(extensibility)。Python可以在多個層次上拓展。從高層上,你可以引入.py文件。在底層,你可以引用C語言的庫。Python程序員可以快速的使用Python寫.py文件作為拓展模塊。但當性能是考慮的重要因素時,Python程序員可以深入底層,寫C程序,編譯為.so文件引入到Python中使用。Python就好像是使用鋼構建房一樣,先規定好大的框架。而程序員可以在此框架下相當自由的拓展或更改。
最初的Python完全由Guido本人開發。Python得到Guido同事的歡迎。他們迅速的反饋使用意見,並參與到Python的改進。Guido和一些同事構成Python的核心團隊。他們將自己大部分的業余時間用於hack Python (也包括工作時間,因為他們將Python用於工作)。隨後,Python拓展到CWI之外。Python將許多機器層面上的細節隱藏,交給編譯器處理,並凸顯出邏輯層面的編程思考。Python程序員可以花更多的時間用於思考程序的邏輯,而不是具體的實現細節 (Guido有一件T恤,寫著:人生苦短,我用Python)。這一特徵吸引了廣大的程序員。Python開始流行。
python的發展
到今天,Python的框架已經確立。Python語言以對象為核心組織代碼(Everything is object),支持多種編程範式(multi-paradigm),採用動態類型(dynamic typing),自動進行內存回收(garbage collection)。Python支持解釋運行(interpret),並能調用C庫進行拓展。Python有強大的標准庫 (battery included)。由於標准庫的體系已經穩定,所以Python的生態系統開始拓展到第三方包。這些包,如Django, web.py, wxpython, numpy, matplotlib,PIL.
Python從其他語言中學到了很多,無論是已經進入歷史的ABC,還是依然在使用的C和Perl,以及許多沒有列出的其他語言。可以說,Python的成功代表了它所有借鑒的語言的成功。同樣,Ruby借鑒了Python,它的成功也代表了Python某些方面的成功。每個語言都是混合體,都有它優秀的地方,但也有各種各樣的缺陷。同時,一個語言「好與不好」的評判,往往受制於平台、硬體、時代等等外部原因。
⑼ 如何讓python調用C和C++代碼
二、Python調用C/C++1、Python調用C動態鏈接庫Python調用C庫比較簡單,不經過任何封裝打包成so,再使用python的ctypes調用即可。(1)C語言文件:pycall.c[html]viewplain/***gcc-olibpycall.so-shared-fPICpycall.c*/#include#includeintfoo(inta,intb){printf("youinput%dand%d\n",a,b);returna+b;}(2)gcc編譯生成動態庫libpycall.so:gcc-olibpycall.so-shared-fPICpycall.c。使用g++編譯生成C動態庫的代碼中的函數或者方法時,需要使用extern"C"來進行編譯。(3)Python調用動態庫的文件:pycall.py[html]viewplainimportctypesll=ctypes.cdll.LoadLibrarylib=ll("./libpycall.so")lib.foo(1,3)print'***finish***'(4)運行結果:2、Python調用C++(類)動態鏈接庫需要extern"C"來輔助,也就是說還是只能調用C函數,不能直接調用方法,但是能解析C++方法。不是用extern"C",構建後的動態鏈接庫沒有這些函數的符號表。(1)C++類文件:pycallclass.cpp[html]viewplain#includeusingnamespacestd;classTestLib{public:voiddisplay();voiddisplay(inta);};voidTestLib::display(){cout#include#includeintfac(intn){if(n<2)return(1);/*0!==1!==1*/return(n)*fac(n-1);/*n!==n*(n-1)!*/}char*reverse(char*s){registerchart,/*tmp*/*p=s,/*fwd*/*q=(s+(strlen(s)-1));/*bwd*/while(p
⑽ python怎麼調用c的動態鏈接庫
Python調用C/C++動態鏈接庫的需求
在自動化測試過程中,難免會遇到語言混合使用的情況,這不,我們也遇到了。初步決定採用Robot Framework作為自動化測試框架後,其支持Java和Python,而Python作為主流的語言,怎麼能放棄使用它的機會^_^。 然而產品採用是古老90年代開發的C/S結構,因為古老,當時也沒有考慮到對產品的測試進行自動化,Client端並沒有預留CLI(Command Line interface)形式的介面,真是雪上加霜啊。
那怎麼自動化?採用AutoIT來對客戶端界面進行自動化測試?可惜AutoIT對當初開發採用的控制項識別不是很好,如果採用控制項所在位置來進行控制的方式,又會導致自動化測試並不是很穩定。那麼!!!只有自己開發介面了,目前在Client端開發出CLI形式的介面,將其封裝為DLL,然後在Robot FrameWork框架中採用Python對DLL進行調用。任務艱巨哪!
Python調用DLL例子
示例一
首先,在創建一個DLL工程(本人是在VS 2005中創建),頭文件:
[cpp] view plain 在CODE上查看代碼片派生到我的代碼片//hello.h
#ifdef EXPORT_HELLO_DLL
#define HELLO_API __declspec(dllexport)
#else
#define HELLO_API __declspec(dllimport)
#endif
extern "C"
{
HELLO_API int IntAdd(int , int);
}
CPP文件:
[cpp] view plain 在CODE上查看代碼片派生到我的代碼片//hello.cpp
#define EXPORT_HELLO_DLL
#include "hello.h"
HELLO_API int IntAdd(int a, int b)
{
return a + b;
}
這里有兩個注意點:
(1)弄清楚編譯的時候函數的調用約定採用的__cdecl還是__stdcall,因為根據DLL中函數調用約定方式,Python將使用相應的函數載入DLL。
(2)如果採用C++的工程,那麼導出的介面需要extern "C",這樣python中才能識別導出的函數。
我的工程中採用__cdecl函數調用約定方式進行編譯鏈接產生hello.dll,然後Python中採用ctypes庫對hello.dll進行載入和函數調用:
[python] view plain 在CODE上查看代碼片派生到我的代碼片from ctypes import *
dll = cdll.LoadLibrary('hello.dll');
ret = dll.IntAdd(2, 4);
print ret;
OK,一個小例子已經完成了,如果你感興趣,但還沒試過,那就嘗試一下吧。
示例二
示例一隻是一個"hello world"級別的程序,實際運用中更多的需要傳遞數據結構、字元串等,才能滿足我們的需求。那麼這個示例將展示,如何傳遞數據結構參數,以及如何通過數據結構獲取返回值。
首先編寫DLL工程中的頭文件:
[cpp] view plain 在CODE上查看代碼片派生到我的代碼片//hello.h
#ifdef EXPORT_HELLO_DLL
#define HELLO_API __declspec(dllexport)
#else
#define HELLO_API __declspec(dllimport)
#endif
#define ARRAY_NUMBER 20
#define STR_LEN 20
struct StructTest
{
int number;
char* pChar;
char str[STR_LEN];
int iArray[ARRAY_NUMBER];
};
extern "C"
{
//HELLO_API int IntAdd(int , int);
HELLO_API char* GetStructInfo(struct StructTest* pStruct);}
CPP文件如下:
[cpp] view plain 在CODE上查看代碼片派生到我的代碼片//hello.cpp
#include <string.h>
#define EXPORT_HELLO_DLL
#include "hello.h"
HELLO_API char* GetStructInfo(struct StructTest* pStruct){
for (int i = 0; i < ARRAY_NUMBER; i++)
pStruct->iArray[i] = i;
pStruct->pChar = "hello python!";
strcpy (pStruct->str, "hello world!");
pStruct->number = 100;
return "just OK";
}
GetStructInfo這個函數通過傳遞一個StructTest類型的指針,然後對對象中的屬性進行賦值,最後返回"just OK".
編寫Python調用代碼如下,首先在Python中繼承Structure構造一個和C DLL中一致的數據結構StructTest,然後設置函數GetStructInfo的參數類型和返回值類型,最後創建一個StructTest對象,並將其轉化為指針作為參數,調用函數GetStrcutInfo,最後通過輸出數據結構的值來檢查是否調用成功:
[python] view plain 在CODE上查看代碼片派生到我的代碼片from ctypes import *
ARRAY_NUMBER = 20;
STR_LEN = 20;
#define type
INTARRAY20 = c_int * ARRAY_NUMBER;
CHARARRAY20 = c_char * STR_LEN;
#define struct
class StructTest(Structure):
_fields_ = [
("number", c_int),
("pChar", c_char_p),
("str", CHARARRAY20),
("iArray", INTARRAY20)
]
#load dll and get the function object
dll = cdll.LoadLibrary('hello.dll');
GetStructInfo = dll.GetStructInfo;
#set the return type
GetStructInfo.restype = c_char_p;
#set the argtypes
GetStructInfo.argtypes = [POINTER(StructTest)];objectStruct = StructTest();
#invoke api GetStructInfo
retStr = GetStructInfo(byref(objectStruct));#check result
print "number: ", objectStruct.number;
print "pChar: ", objectStruct.pChar;
print "str: ", objectStruct.str;
for i,val in enumerate(objectStruct.iArray):
print 'Array[i]: ', val;
print retStr;
總結
1. 用64位的Python去載入32位的DLL會出錯
2. 以上只是些測試程序,在編寫Python過程中盡可能的使用"try Except"來處理異常3. 注意在Python與C DLL交互的時候位元組對齊問題4. ctypes庫的功能還有待繼續探索