python調用C++: ctypes庫教程

2021-12-28 機器學習備忘錄
一、準備C++代碼

注意,使用ctypes庫調用C++代碼時,由於C++相比於C多了函數重載的特性,因此一個函數不能僅僅使用其名字來確定,為了便於調用,每一個C++函數都需要增加標識符:

extern "C"

示例代碼如下:

#include <iostream>
using namespace std;

typedef struct StructTest
{
    char* name;
    int age;
    float score[2];
}StructData, *StructPtr;

class TestDataStructure
        {
        public:
            int receiveInt(int a);
            double receiveDouble(double d);
            char receiveChar(char c);
            char* receiveString(char* s);
            StructData receiveStruct(StructData st);
            StructPtr receiveStructPtr(StructPtr p);
            StructPtr receiveStructArray(StructData vst[], int size);
        };

int TestDataStructure::receiveInt(int a) {
    cout << a << " in c++" << endl;
    return a;
}

double TestDataStructure::receiveDouble(double d) {
    cout << d << " in c++" << endl;
    return d;
}

char TestDataStructure::receiveChar(char c) {
    cout << c << " in c++" << endl;
    return c;
}

char* TestDataStructure::receiveString(char* s) {
    cout << s << " in c++" << endl;
    return s;
}

StructData TestDataStructure::receiveStruct(StructData st) {
    cout << st.name << " " << st.age << " " << st.score[2] << " in c++" << endl;
    return st;
}

StructPtr TestDataStructure::receiveStructPtr(StructPtr p) {
    cout << p->name << " " << p->age << " " << p->score[2] << " in c++" << endl;
    return p;
}

StructPtr TestDataStructure::receiveStructArray(StructData vst[], int size) {
    cout << vst[0].name << " in c++" << endl;
    cout << vst[1].name << " in c++" << endl;
    return &vst[0];
}

extern "C" {
    TestDataStructure obj;

    int passInt(int a) {
        return obj.receiveInt(a);
    }

    double passDouble(double d){
        return obj.receiveDouble(d);
    }

    char passChar(char c) {
        return obj.receiveChar(c);
    }

    char* passString(char* s){
        return obj.receiveString(s);
    }

    StructData passStruct(StructData st){
        return obj.receiveStruct(st);
    }

    StructPtr passStructPtr(StructPtr p){
        return obj.receiveStructPtr(p);
    }

    StructPtr passStructArray(StructData vst[], int size){
        return obj.receiveStructArray(vst, size);
    }
}

二、編譯動態連結庫

使用如下命令編譯C++,可以將main.cpp文件編譯為libTest.so文件,保存目錄為根目錄。

g++ -o libTest.so -shared -fPIC main.cpp

三、python調用

使用python的ctypes庫可以很方便地對其進行調用。

轉換原則如下:

所有的C++關鍵字及其特有的使用方式均不能出現在.h文件裡,.h中僅有C函數的包裝函數聲明

在class.cpp中實現對類的成員函數接口轉換的函數,包括對類內成員的讀寫函數get() and set()

如果要在包裝函數中要實例化對象,儘量用new constructor()的將對象的內存實例化在堆中,否則對象會被析構

記得在所有包含函數聲明的文件中加入以下關鍵字,聲明該函數為C函數,否則該函數的符號不會記錄在二進位文件中

C和python的數據格式需要對應,否則可能產生亂碼

上圖為數據轉換格式對應。python示例代碼如下:

import ctypes

lib = ctypes.cdll.LoadLibrary("/home/liangqian/PycharmProjects/Gauss/test_dataset/TestLib.so")

print("Test int io...")
func = lib.receiveInt
func.argtypes = [ctypes.c_int]
func.restype = ctypes.c_int
print(func(100))
print()

print("Test double io...")
func = lib.receiveDouble
func.argtypes = [ctypes.c_double]
func.restype = ctypes.c_double
print(func(3.14))
print()

print("Test char io...")
func = lib.receiveChar
func.argtypes = [ctypes.c_char]
func.restype = ctypes.c_char
print(func(ctypes.c_char(b'a')))
print()

print("Test string io...")
func = lib.receiveString
func.argtypes = [ctypes.c_char_p]
func.restype = ctypes.c_char_p
print(func(b"(This is a test string.)"))
print()

print("Test struct io...")


class Struct(ctypes.Structure):
    _fields_ = [('name', ctypes.c_char_p),
                ('age', ctypes.c_int),
                ('score', ctypes.c_float * 3)]


lib.argtypes = [Struct]
lib.receiveStruct.restype = Struct
array = [85, 93, 95]
st = lib.receiveStruct(Struct(b'XiaoMing', 16, (ctypes.c_float * 3)(*array)))
print(str(st.name) + ' ' + str(st.age) + ' ' + str(st.score[0]) + ' in python')
print()

print('Test struct pointer io...')
lib.receiveStructPtr.restype = ctypes.POINTER(Struct)
lib.receiveStructPtr.argtypes = [ctypes.POINTER(Struct)]
p = lib.receiveStructPtr(Struct(b"XiaoHuang", 19, (ctypes.c_float * 3)(*array)))
print(str(p.contents.name) + ' ' + str(p.contents.age) + ' ' + str(p.contents.score[0]) + ' in python')
print()

print('Test struct array io...')
lib.receiveStructArray.restype = ctypes.POINTER(Struct)
lib.receiveStructArray.argtypes = [ctypes.ARRAY(Struct, 2), ctypes.c_int]
array = [Struct(b'student1', 19, (ctypes.c_float * 3)(91, 92, 93)),
         Struct(b'student2', 18, (ctypes.c_float * 3)(88, 95, 92))]
p = lib.receiveStructArray(ctypes.ARRAY(Struct, 2)(*array), 2)
print(str(p.contents.name) + ' ' + str(p.contents.age) + ' ' + str(p.contents.score[2]) + ' in python')

相關焦點

  • 簡單的Python調用C++程序
    - 2、將C/C++程序編譯成動態庫。- 3、在Python中調用編譯生成的庫。Python在調用C/C++程序時有一些不同,需要注意。1、Python調用C函數Python調用C語言程序比較簡單,將C語言程序編譯好,再使用python中的ctypes模塊調用即可。
  • python3使用ctypes在windows中訪問C和C++動態連結庫函數示例
    python3使用ctypes在windows中訪問C和C++動態連結庫函數示例這是我們的第一個示例,我們儘量簡單,不傳參,不返回,不訪問其他的動態連結庫一 測試環境介紹和準備二 C/C++部分代碼1 首先完成C/C++的動態連結庫,與做python擴展庫不同,ctypes調用的c++庫其實與python沒有代碼關聯,只是提供了開放公共標準。
  • python+C、C++混合編程的應用
    python與C/C++混合編程的本質是python調用C/C++編譯的動態連結庫,關鍵就是把python中的數據類型轉換成c/c++中的數據類型,給編譯函數處理,然後返回參數再轉換成python中的數據類型。
  • Python 通過 ctypes 調用 C 程序實例
    (點擊上方藍字,快速關注我們)來源:思誠之道http://www.bjhee.com/python-ctypes.html
  • Python使用ctypes模塊調用DLL函數之C語言數組與numpy數組傳遞
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了
  • Python:ctypes模塊調用go代碼
    簡介:ctypes 是 Python 的外部函數庫。
  • Python使用ctypes模塊調用DLL函數之複數數組的參數傳遞
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,前面多篇文章中已經講了傳遞數值/指針/字符串參數、傳遞結構體參數、傳遞普通數組類型的例子,大家可以回看一下,這樣可以更好的理解本次要講的內容。
  • Python使用ctypes模塊調用DLL函數之傳遞結構體參數
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢
  • python使用ctypes模塊調用DLL函數之傳遞數值、指針與字符串參數
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢。
  • 如何用 Python 監聽軟體?
    ctypes 是 Python 的外部函數庫。它提供了與 C 兼容的數據類型,並允許調用 DLL 或共享庫中的函數。可使用該模塊以純 Python 形式對這些庫進行封裝。(), 0)更多關於 ctypes庫 使用教程可查看Python官方文檔:https://docs.python.org/zh-cn/3.7/library/ctypes.html上面我們說過 監視低級鍵盤輸入事件(WH_KEYBOARD_LL
  • Python與C/C++混合編程
    完整的選項可移步至MSDN文檔查看https://docs.microsoft.com/en-us/cpp/build/reference/dumpbin-options?view=msvc-160 本文主要用dumpbin查看動態庫函數:#dumpbin -exports xxx.dll
  • Python案例|混用C函數
    使用Python自帶的 ctypes 模塊在Python內直接調用C的動態連結庫代碼,這對於調用現有的庫,一些不開源的庫很有用.用Python自帶的c API來寫模塊,當然是用c/c++來編寫用 Cython 的新語法來寫擴展模塊,這種新語法看起來既像Python又像C,是個語法混合體,但還有很多人推崇, 其優點是可以同時調用C函數和Python函數。但其語法小編著實看著頭大,有興趣的可以自行研究.
  • Python 調用 C 模塊以及性能分析
    和python的數據類型的對應關係ctypes type ctype Python typec_char char 1-character stringc_wchar wchar_t 1-character unicode stringc_byte char int/longc_ubyte unsigned char int/long
  • ctypes(一) — 初識
    使用C來輔助Python解決某些特殊情況下的性能問題,成了如今Python社區中最為普遍的方案,很多人不知道,事實上很多我們常用的庫都利用了這一特性。數據兼容層由於Python這一特性是一個大家族,我們先來了解一下Python與C之間做的一個兼容層模塊 — ctypes 模塊。
  • scratch/python/c++,小孩學編程學哪個好?
    如果從零開始學習scratch,可以關注本號,本號將發布公益性教程。編程貓是我國的一款優秀軟體,它模仿了scratch,並進行了大規模改進,但基本邏輯都是一樣的。編程貓的公司點貓科技獲得了多輪融資,並積極進行教材化操作,應該是很有前途的軟體。不過對於編程貓的積木設置,不少人有不同的看法。
  • 指南:使用ctypes優化Python代碼
    ctypesctypes是一個模塊,它允許你通過Python代碼與C代碼進行通信,而不需要使用子進程或類似的模塊來從CLI運行另一個進程。每個元組是(<variable-name>, <ctypes.TYPE>)。ctypes還有像c_char (char)和c_char_p (*char)這樣的類型。ctypes還包括POINTER(),它會從傳遞給它的任何類型創建一個指針類型。
  • 使用C++調用python3模塊中的類/函數詳細經驗
    零、測試環境與前提條件 一、準備階段要想實現C調用python需要用到Python庫的幫忙,如Python.h;由於依賴文件們在安裝Python
  • Python與C/C++之間還可以這樣玩?
    一、問題Python模塊和C/C++的動態庫間相互調用在實際的應用中會有所涉及,在此作一總結。二、Python調用C/C++1、Python調用C動態連結庫Python調用C庫比較簡單,不經過任何封裝打包成so,再使用python的ctypes調用即可。
  • 【超詳細 | Python】CS免殺-Shellcode Loader原理(python)
    最近在學習cs免殺,由於比較菜只懂python語言,就先了解py是如何實現加載shellcode寫入內存的。