當前位置:首頁 » 編程語言 » python封裝c

python封裝c

發布時間: 2023-01-04 02:36:36

❶ 如何在python中使用C/C++結構體等復雜類型

C封裝了一個Dll,名為SpjMatlabTest.dll,暴露實現:
typedef struct{
double *Min;
double *Max;
} ST_TESTLIMIT;
typedef struct{
int NumVDIVs;
int NumPts;
double *TestedVDIVs; // Pointer to first element in array that is 1xNumVDIVs long.
double *TestPtsinFracFS; // Pointer to first element in array that is 1xNumPts long.
double *VerrinFracFS; // Pointer to first element in array that is NumVDIVs*NumPts*NumChans long.
double DCAcc;
double OffConstAcc;
double *GainErrorPct; // Pointer to first element in array of NumVDIVs*NumChans long.
double *OffsetErrorFracFS; // Pointer to first element in array of NumVDIVs*NumChans long.
double *MaxNonLinearityFracFS; // Pointer to first element in array of NumVDIVs*NumChans long.
double GainErrorLimitPctAbs;
double TDIV;
} ST_LINACCD1M;
#include <windows.h>
#ifndef BUILD_DLL
//Define the function prototypes to be used by the calling application.
typedef bool (__cdecl *MATLABAPPINITIALIZE)(void);
typedef bool (__cdecl *MATLABAPPTERMINATE)(void);
typedef bool (__cdecl *LINACCD1M)(ST_LINACCD1M *stOutput, const bool *Channels, const char *ScopeAddress, const int GPIBAddress);
typedef void (__cdecl *LINACCD1MCLEANUP)(void);
#endif
現在需要在py代碼中使用ST_LINACCD1M結構體。
測試代碼:

from ctypes import *
class C_ST_LINACCD1M(Structure):
_fields_ = [('NumVDIVs', c_int),
('NumPts', c_int),
('TestedVDIVs', c_void_p),
('TestPtsinFracFS', c_void_p),
('VerrinFracFS', c_void_p),
('DCAcc', c_double),
('OffConstAcc', c_double),
('GainErrorPct', c_void_p),
('OffsetErrorFracFS', c_void_p),
('MaxNonLinearityFracFS', c_void_p),
('GainErrorLimitPctAbs', c_double),
('TDIV', c_double)]

import sys
def visit():
info = C_ST_LINACCD1M()
#print info.sth...
dllName = "SpjMatlabTest.dll"
dllload = windll.LoadLibrary(dllName)
print dllload
py_LINACCD1M = dllload.LINACCD1M
py_LINACCD1M.argtypes = [c_void_p, c_void_p, c_char_p, c_int]
#.restypep = c_void_p
para_in_1 = True
para_in_2 = c_char_p("/0")
para_in_3 = 0
nRetVal = dllload.LINACCD1M(byref(info), para_in_1, para_in_2, para_in_3)
#print info.sth...
if __name__ == "__main__":
visit()
打完收工。

❷ python與c的區別

Python這類解釋型的語言適合快速搭建原型,快速完成那些用過即扔的小程序,或者寫一些對性能不很敏感的網路應用。C這類編譯型的語言適合寫業務邏輯清楚明確,性能要求高,寫後不會經常變化的程序,或者是庫。一次編寫,長期運行。

Python的優點就是C的缺點,反之也一樣。解釋型語言確實寫起來很方便,但是由於類型自動推導,會造成一些bug不容易發現,有的只能在運行時刻才能爆發,對重要場合還是很讓人懊惱的。編譯型語言能在編譯期發現更多問題,但也會花大量時間和代碼處理各種類型轉換的無聊問題,這點又是解釋型的優點。編程語言的一個發展趨勢是編譯型和解釋型語言正在互相融合,彼此吸收借鑒,現在類型自動推導也在很多編譯型語言里有了。

可以結合C和Python使用,用C寫核心的功能,穩定不變的部分,封裝成庫,用Python完成頻繁變化的業務邏輯部分,C+Python是一對強大組合。

❸ 如何將C++的API封裝成python可調用形式

在C++的庫上面套一層wrapper就可以了。
可以包裝成CPython模塊,也可以包裝成C庫然後用ctypes、cffi調用。
要對付主要是是C++的函數命名和類型。
包裝CPython模塊可以看手冊里「Extending and Embedding」的部分。只要保證initMODULENAME(2.x)或PyInit_MODULENAME(3.x)是extern "C"的就行,手冊里的例子用了PyMODINIT_FUNC這個宏,已經自動給加好了。
包裝C庫就是把所有函數都聲明成extern "C"的,把傳遞的C++類型以C類型替代。舉個例子

namespace enemy {

void first_blood(int id);

} // namespace enemy

void double_kill();
void double_kill(int killer);

class Silencer
{
public:
std::string watch_and_learn();
};

包裝之後大概是這樣的:

extern "C" {

void enemy_first_blood(int id)
{
enemy::first_blood(id);
}

void double_kill_by_roshan()
{
double_kill();
}

void double_kill_by_hero(int killer)
{
double_kill(killer);
}

void* new_silencer()
{
return new Sliencer;
}

void silencer_watch_and_learn(void *instacne, char *buffer)
{
std::string what = reinterpret_cast<Silencer*>(instance)->watch_and_learn();
strcpy(buffer, what.c_str());
}

void release_silencer(void *instacne)
{
delete reinterpret_cast<Silencer*>(instance);
}

} // extern "C"

❹ 如何讓python調用C和C++代碼

如何讓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中包含調試信息

*/
#pragma comment(lib, "python25.lib")
//先不管
static PyObject* mb_showMsg(PyObject* self, PyObject *args); /*
如果你的擴展是mb,那麼必須實現一個initmb函數,並且從dll中導出這個函數,但我們在python中調用import mb時,python會去dll里去調用
initmb函數,這個函數告訴python我們有些什麼函數,該怎麼告訴python我們有一個showMsg函數呢?下面詳解 */
//必須extern "C"下,這樣不會在C++編譯器里不會更改掉導出的函數名字,我第一次就犯了這樣的錯誤
extern "C" __declspec(dllexport) void initmb() { /*
當調用mb.showMsg("Python's really amazing, I kindda love it!")時, 相當於你告訴python我有一個showMsg函數,我們怎麼告訴python去調用我們dll里的mb_showMsg函數呢?技巧就是下面的方式, 定義一個字典數據結構,key => showMsg, value =>mb_showMsg,METH_VARARGS是函數調用方式,仔細查手冊吧 */
static PyMethodDef mbMethods[] = { {"showMsg", mb_showMsg, METH_VARARGS},
{NULL, NULL, NULL} /*sentinel,哨兵,用來標識結束*/ };
//告訴python我們的模塊名叫mb, 模塊包含的函數都在mbMethods字典里 PyObject *m = Py_InitMole("mb", mbMethods); } /*
接下來實現核心功能showMsg */
//第一個self參數我們用不著,具體查手冊,第二個參數是python傳給我們的參數,它是一個python的參數tuple
static PyObject* mb_showMsg(PyObject* self, PyObject *args) {
//我們的showMsg函數需要的是一個字元串參數 const char* msg = NULL; /*

調用特殊參數解碼python傳遞給我們的參數,s是string,我們傳遞接收參數的變數地址,
如果你的功能函數需要兩個參數,在PyArg_parseTuple後面繼續添加接受參數的變數地址,
這個函數的原型是類似printf的不定參數的形式
PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...); */
if (!PyArg_ParseTuple(args, "s", &msg)) return NULL;
//調用MB
int r = ::MessageBox(NULL, "hello", "Caption:Form C mole", MB_ICONINFORMATION | MB_OK);
//返回值
return Py_BuildValue("i", r); }
將上面這段混雜著大量注釋的代碼拷貝到你的編輯器里,然後編譯生成mb.dll,修改後綴成mb.pyd,然後拷貝到python的DLLs目錄下,打開idle(python的交互程序),寫入代碼: import mb
mb.showMsg("Python's really amazing, I kindda love it!")
可以看到彈出來一個MessageBox。

❺ 如何用Python封裝C語言的字元串處理函數

S.find(substr, [start, [end]]) #返回S中出現substr的第一個字母的標號,如果S中沒有substr則返回-1。start和end作用就相當於在S[start:end]中搜索
S.index(substr, [start, [end]]) #與find()相同,只是在S中沒有substr時,會返回一個運行時錯誤
S.rfind(substr, [start, [end]]) #返回S中最後出現的substr的第一個字母的標號,如果S中沒有substr則返回-1,也就是說從右邊算起的第一次出現的substr的首字母標號 !

❻ Python寫好的演算法代碼,下一步用C還是C++進行重寫封裝給別人調用比較好

底層都用py了,上面還管什麼效率
用什麼都一樣
c/c++/py隨你喜歡了

❼ 如何用Python封裝C語言的字元串處理函數

在C語言中,字元串處理是每天都要面對的問題。我們都知道C語言中其實並沒有一種原生的字元串類型,『字元串』在C語言里只是一種特殊的以''結尾的字元數組。因此,如何將C語言與更高層次的Python語言在『字元串』處理這個問題上對接是一個有難度的問題。所幸有swig這種強大的工具。

如何封裝一個函數,它修改參數字元串的內容

假如有這樣一個C語言的函數,
<!-- lang: cpp -->
void FillZero(char* pc,size_t * piLen)
{
size_t i=0;
while(i++<*piLen/2 )
*pc++ = '0';
*pc = 0;
*piLen = i+1;
}

這個函數的功能是把字元串變成n個0。不過我們更關注函數的形式。這樣的函數,表面上看char* pc是函數的參數,可是實際上它才是函數的返回值和執行的結果。piLen這個參數既是pc的最大長度,也是新的字元串的長度。我們直接用python封裝,看看運行結果。

Type "help", "right", "credits" or "license" for more information.
>>> import cchar
>>> s='123456'
>>> cchar.FillZero(s,6)
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: in method 'FillZero', argument 2 of type 'size_t *'

結果差強人意,不是我們想要得到的結果。函數的第二個參數為size_t* 我們很難用python來表示,而且python中也不存在既是輸入,也是輸出的參數。

swig有一個標准庫,其中有一個cstring.i文件就是用來解決C語言字元串類型的問題。

我們在.i文件中加入這樣幾行
<!-- lang: cpp -->
%include "cstring.i"
%cstring_output_withsize(char* pc,size_t* pi)
void FillZero(char* pc, size_t* pi);

然後運行看結果

Type "help", "right", "credits" or "license" for more information.
>>> import cchar
>>> cchar.FillZero(10)
'00000\x00'
>>> s=cchar.FillZero(10)
>>> print s
00000

我們看函數的變化。首先在python里, FillZero變成了只有一個參數的函數。然後函數的返回值變成了一個字元串。其實cstring_output_size其實是一個宏,通過這個宏的定義改變了函數的形式,直接在Python中得到我們想要的結果。

其實類似cstring_output_size的宏還有好幾個,我列舉一下:

cstring_output_allocate(char *s,free($1));
第一個參數是指向字元串地址的指針,第二個參數為釋放空間的方法。
大家考慮這一下這樣的函數:
void foo(char* & s)
{

s = (char*)malloc(10);
memcpy(s,"123456789",9);

}

s這個參數表面上看是輸入,實際上是函數真正的輸出。 函數中真正改變的東西是char&s指向的字元串的值。而且char&這個類型,

python或者其他腳本語言里應該都沒有對應的類型。那麼我們用cstring_output_allocate將這個函數轉換成另外一個形式的python或者其他腳本語言的函數。轉換後的函數其實是這樣的,以python為例str
foo()。
<!-- lang: cpp -->
%mole a
%include "cstring.i"
%{
void foo(char*& s);
%}
%cstring_output_allocate(char *&s, free(*$1));
void foo(char *&s);

在python中的調用:

<!-- lang: python -->
>>> import a
>>> a.foo()
'123456789'
>>>

cstring_output_maxsize(char *path, int maxpath);
第一個參數也是可以改變的字元串首地址,第二個參數為字元串的最大長度。在Python中調用的時候,只有maxpath這個參數,返回字元串。
cstring_output_allocate(char *s, free($1));
第一個參數為指向字元串首地址的指針,第二個參數為釋放指針的方法。這個宏主要是封裝一種直接在函數內部malloc空間的函數。在Python中調用時沒有參數,直接返回字元串。
cstring_output_allocate_size(char *s, int slen, free(*$1));
這個相當於前面兩個函數的組合。在函數內部malloc空間,然後將字元串長度通過slen返回。其實在調用的時候非常簡單,沒有參數,直接返回字元串。

如何處理c++的std::string

std::string是C++標准類庫STL中常見的類。在平時工作中大家肯定是沒少用。在python中如何封裝std::string? swig提供了標准庫

例如函數:
<!-- lang: cpp -->
string Repeat(const string& s)
{
return s+s;
}

只要在swig中加入這樣幾行:
<!-- lang: cpp -->
%include "std_string.i"
using namespace std;
string Repeat(const string& s);

運行結果:

Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
[GCC 4.4.5] on linux2
Type "help", "right", "credits" or "license" for more information.
>>> import cchar
>>> cchar.Repeat('123')
'123123'

使用起來很方便,但需要注意的是,假如函數的參數的內容是可以被修改,就不能用這種方式封裝。
例如:
<!-- lang: cpp -->
void repeat(string s)
{
s+=s;
}

這樣的函數直接使用 'std_string.i' 就是無效的。遇到這種函數,只能用C語言封裝成 void repeat(chars, int maxsize), 再用swig調用 'cstring_output_withsize' 這個宏再封裝一次了。

❽ pb調用Python封裝dll

Cython將Python文件轉為c文件。
在調用DLL之前,最好先建立另一個空項目將pch.cpp裡面的代碼復制過去測試一下直接調用listAdd函數能不能成功。
新建空項目,將生成dll和lib文件以及原Python文件test_numpy.py復制到新項目的路徑下,新建main.cpp,用於調用dll,運行之前,需要配置一下項目屬性,將之前生成的lib文件加入到鏈接器裡面,再運行程序。

熱點內容
資料庫組別 發布:2025-07-05 06:15:53 瀏覽:710
我的世界伺服器怎樣設置新手裝備只能拿一次 發布:2025-07-05 06:15:53 瀏覽:985
緩存40集電視劇需要多少流量 發布:2025-07-05 05:56:44 瀏覽:64
iso怎麼解壓到u盤 發布:2025-07-05 05:49:02 瀏覽:890
php參數設置 發布:2025-07-05 05:49:00 瀏覽:995
javacharacter 發布:2025-07-05 05:38:36 瀏覽:735
伺服器pcid地址怎麼看 發布:2025-07-05 05:35:40 瀏覽:384
安卓系統賺錢靠什麼 發布:2025-07-05 05:28:06 瀏覽:159
編譯不出來的原因 發布:2025-07-05 05:14:00 瀏覽:69
絕地求生國際服如何選擇伺服器 發布:2025-07-05 05:08:56 瀏覽:66