本文目錄一覽:
- 1、我會Python,且第三方系統有接口,我應該如何通過Python去調用第三方系統的接口,進行對接?
- 2、怎樣讓Python腳本與C++程序互相調用
- 3、python 怎麼調用odbc
- 4、從Python調用CAPL函數問題,怎麼解決
- 5、如何讓python調用C和C++代碼
- 6、python 怎麼調用c語言接口
我會Python,且第三方系統有接口,我應該如何通過Python去調用第三方系統的接口,進行對接?
python因為良好的編碼性和擴展庫正被大規模的使用,但他有兩個缺點:1、代碼可見;2、執行效率低,於是在實際應用中經常會把高效和核心代碼用C/C++實現,業務部分用python實現。這就需要進行混合編程,本文對python調用動態庫的方法及注意事項進行記錄
主題
python標準庫函數中提供了調用動態庫的包————ctypes
加載動態庫
查找動態庫ctypes.util.find_library
根據動態庫調用方式的不同,可以分為cdecl和stdcall兩種,這兩種方式的主要區別見下表。後面的例子以cdecl調用方式為例,stdcall類同。
調用標準 內存棧維護者 函數名
cdecl 調用者 前面加下劃線,後面加“@”符號和參數的字節數
stdcall 被調用者 在輸出函數名前面加下劃線
* ctypes加載動態庫有兩種方式。構造類對象libc = CDLL(“libtestlib.dll”)和實例化instancelibc = cdll.LoadLibrary(“libtestlib.dll”)。這兩種方式都會返回一個動態庫操作的句柄,
怎樣讓Python腳本與C++程序互相調用
二、Python調用C/C++
1、Python調用C動態鏈接庫
Python調用C庫比較簡單,不經過任何封裝打包成so,再使用python的ctypes調用即可。
(1)C語言文件:pycall.c
[html] view plain copy
/***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 copy
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 copy
#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:”aendl;
}
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 copy
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 copy
#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=”numendl;
cout”—end—“endl;
}
(2)編譯成二進制可執行文件:g++ -o testmain main.cpp。
(3)Python調用程序:main.py
[html] view plain copy
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 copy
#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* Module_func()的包裝函數;c、為每個模塊增加一個型如PyMethodDef ModuleMethods[]的數組;d、增加模塊初始化函數void initModule()。
python 怎麼調用odbc
入門
連接到數據庫
調用connect方法並傳入ODBC連接字符串,其會返回一個connect對象。通過connect對象,調用cursor()方法,可以獲取一個游標cursor。如下代碼示例:
import pyodbc
#連接示例: Windows系統, 非DSN方式, 使用微軟 SQL Server 數據庫驅動
cnxn =pyodbc.connect(‘DRIVER={SQL Server};SERVER=localhost;PORT=1433;DATABASE=testdb;UID=me;PWD=pass’)
#連接示例: Linux系統, 非DSN方式, 使用FreeTDS驅動
cnxn =pyodbc.connect(‘DRIVER={FreeTDS};SERVER=localhost;PORT=1433;DATABASE=testdb;UID=me;PWD=pass;TDS_Version=7.0’)
#連接示例:使用DSN方式
cnxn = pyodbc.connect(‘DSN=test;PWD=password’)
# 打開游標
cursor =cnxn.cursor()
以上示例只是標準示例,具體的ODBC連接字符串以你自己使用的驅動為準。
查詢一些數據
所有SQL語句都使用Cursor.execute()方法執行。比如select語句會返回一些結果行,你可以使用游標(Cursor)相關的函數功能(fetchone,fetchall,fetchmany)對結果進行檢索。
Cursor.fetchone 用於返回一個單行( Row)對象:
cursor.execute(“selectuser_id, user_name from users”)
row =cursor.fetchone()
if row:
print(row)
Row 對象是類似一個python元組(tuples),不過也可以通過列名稱來訪問,例如:
cursor.execute(“selectuser_id, user_name from users”)
row =cursor.fetchone()
print(‘name:’,row[1]) # 使用列索引號來訪問數據
print(‘name:’,row.user_name) # 或者直接使用列名來訪問數據
當所有行都已被檢索,則fetchone返回None.
while 1:
row = cursor.fetchone()
if not row:
break
print(‘id:’, row.user_id)
Cursor.fetchall方法返回所有剩餘行並存儲於一個列表中。如果沒有行,則返回一個空列表。(注意:如果有很多行,會造成大量內存佔用。Fetchall會一次性將所有數據查詢到本地,然後再遍歷)
cursor.execute(“selectuser_id, user_name from users”)
rows = cursor.fetchall()
for row in rows:
print(row.user_id, row.user_name)
如果並不在意數據處理時間,可以使用光標本身作為一個迭代器,逐行迭代。這樣可以節省大量的內存開銷,但是由於和數據來回進行通信,速度會相對較慢:
cursor.execute(“selectuser_id, user_name from users”):
for row in cursor:
print(row.user_id, row.user_name)
由於Cursor.execute總是返回遊標(cursor), 所以也可以簡寫成:
for row incursor.execute(“select user_id, user_name from users”):
print(row.user_id, row.user_name)
我們可以在execut中使用”””三重引號,來應用多行SQL字符串。這樣sql的可讀性大大增強。這是python特有的特性:
cursor.execute(
“””
select user_id, user_name
from users
where last_logon ‘2001-01-01’
and bill_overdue = 1
“””)
SQL參數
ODBC支持使用問號作為SQL的查詢參數佔位符。可以在execute方法的SQL參數之後,提供SQL參數佔位符的值:
cursor.execute(
“””
select user_id, user_name
from users
where last_logon ?
and bill_overdue = ?
“””, ‘2001-01-01’, 1)
這樣做可以防止SQL注入攻擊,提高安全性。如果使用不同的參數反覆執行相同的SQL它效率會更高,這種情況下該SQL將只預裝(prepared )一次。(pyodbc只保留最後一條編寫的語句,所以如果程序在語句之間進行切換,每次都會預裝,造成多次預裝。)
Python的DB API指定參數應以序列(sequence)對象傳遞,所以pyodbc也支持這種方式:
cursor.execute(
“””
select user_id, user_name
from users
where last_logon ?
and bill_overdue = ?
“””, [‘2001-01-01’, 1])
插入數據
插入數據使用相同的函數 – 通過傳入insert SQL和相關佔位參數執行插入數據:
cursor.execute(“insertinto products(id, name) values (‘pyodbc’, ‘awesome library’)”)
cnxn.commit()
cursor.execute(“insertinto products(id, name) values (?, ?)”, ‘pyodbc’, ‘awesome library’)
cnxn.commit()
注意:調用cnxn.commit()。發成錯誤可以回滾。具體需要看數據庫特性支持情況。如果數據發生改變,最好進行commit。如果不提交,則在連接中斷時,所有數據會發生回滾。
更新和刪除數據
更新和刪除工作以同樣的方式:通過特定的SQL來執行。通常我們都想知道更新和刪除的時候有多少條記錄受到影響,可以使用Cursor.rowcount來獲取值:
cursor.execute(“deletefrom products where id ?”, ‘pyodbc’)
print(‘Deleted {}inferior products’.format(cursor.rowcount))
cnxn.commit()
由於execute 總是返回遊標(允許你調用鏈或迭代器使用),有時我們直接這樣簡寫:
deleted =cursor.execute(“delete from products where id ‘pyodbc'”).rowcount
cnxn.commit()
注意一定要調用commit。否則連接中斷時會造成改動回滾。
技巧和竅門
引號
於單引號SQL是有效的,當值需要使用單引號時,使用用雙引號包圍的SQL:
cursor.execute(“deletefrom products where id ‘pyodbc'”)
如果使用三重引號, 我們可以這樣使用單引號:
cursor.execute(
“””
delete
from products
where id ‘pyodbc’
“””)
列名稱
Microsoft SQLServer之類的一些數據庫不會產生計算列的列名,在這種情況下,需要通過索引來訪問列。我們也可以使用sql列別名的方式,為計算列指定引用名稱:
row =cursor.execute(“select count(*) as user_count fromusers”).fetchone()
print(‘{}users’.format(row.user_count)
當然也可以直接使用列索引來訪問列值:
count =cursor.execute(“select count(*) from users”).fetchone()[0]
print(‘{}users’.format(count)
注意,上例的首列不能是Null。否則fetchone方法將返回None並且會報NoneType不支持索引的錯誤。如果有一個默認值,經常可以是ISNULL或合併:
maxid =cursor.execute(“select coalesce(max(id), 0) fromusers”).fetchone()[0]
自動清理
連接(默認)在一個事務中。如果一個連接關閉前沒有提交,則會進行當前事務回滾。很少需要finally或except 語句來執行人為的清理操作,程序會自動清理。
例如,如果下列執行過程中任何一條SQL語句出現異常,都將引發導致這兩個游標執行失效。從而保證原子性,要麼所有數據都插入發生,要麼所有數據都不插入。不需要人為編寫清理代碼。
cnxn =pyodbc.connect(…)
cursor = cnxn.cursor()
cursor.execute(“insertinto t(col) values (1)”)
cursor.execute(“insertinto t(col) values (2)”)
cnxn.commit()
從Python調用CAPL函數問題,怎麼解決
你沒有說具體問題是什麼,以下介紹一下capl常見問題
一、capl程序組織
1、全局變量的聲明
–you declare variables that can be read or changed by any part of your CAPL program.
在程序的任何部分都可以讀取和修改。
–It is a good idea to declare messages and timers in this section.
適合定義messages和timers。
2、事件處理
–Event procedures are blocks of code that are executed when an event occurs.
事件發生時執行。
–CAPL allows you to define event procedures for several different kinds of events.
可以為多個不同的事件定義事件處理
–Most of your program code will be in event procedures, since most actions are performed after an event, such as a message being received on the CAN bus.
大多數代碼都寫在事件處理中。
–Event procedures cannot return a value.
事件處理不能有返回值。
3、用戶定義函數
–Your programs can contain procedures that can be used to complement CAPL’s built-in functions.
–These procedures can contain any legal CAPL code and are globally accessible.
–Putting frequently-used code in a procedure makes programs more efficient.
–User-defined functions can return a value of any simple type.
可以有返回值。
二、CAPL文件類型
★兩種
*.CAN 包含CAPL程序(ASCII 文本格式)
*.CBF 編譯.CAN文件得到(二進制文件),只能被CANslyzer或CANoe執行。
三、CAPL數據類型
char 8bit unsigned
byte 8bit unsigned
int 16bit signed
word 16bit unsigned
long 32bit signed
dword 32bit unsigned
float 64bit signed
double 64bit signed
message 一條通信消息
timer 秒級計時器
msTimer 毫秒級計時器
四、運算符
(雷同c語言,只列部分)
位操作部分:
= compound assignment(left shift)
= compound assignment(right shift)
= AND
^= XOR
|= OR
五、控制結構
1、if()
{
}
else
{
}
2、switch()
{
case :
default:
}
3、while()
{}
4、do{}while();
5、for(;;){}
6、break continue
7、this
如何讓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),假如我們接下來要寫的擴展module名為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_InitModule(“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 module”, 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語言接口
ctypes: 可直接調用c語言動態鏈接庫。
使用步驟:
1 編譯好自己的動態連接庫
2 利用ctypes載入動態連接庫
3 用ctype調用C函數接口時,需要將python變量類型做轉換後才能作為函數參數,轉換原則見下圖:
4 Python若想獲取ctypes調用的C函數返回值,需要先指定返回值類型。我們將在接下來的完整Sample中看到如何使用。
#Step 1: test.c#include stdio.h
int add(int a, int b)
{
return a + b;
}#Step 2: 編譯動態鏈接庫 ( 如何編譯動態鏈接庫在本文不詳解,網上資料一大堆。)gcc -fPIC -shared test.c -o libtest.so
#Step 3: test.py
from ctypes import *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)
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/259608.html