• Python ctypes调用clib代码示例


    通过c/c++编写动态链接库,再用Python调用写好的函数,可以有效利用c/c++程序的高效与Python的便捷。Python的ctypes库提供了相对便捷的clib调用。

    下述代码在Python3中成功运行,但是Python2会报错,原因尚未深究。

    C++

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define true 1
    #define false 0
    
    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;  
    }
    
    typedef struct StructPointerTest{
        char name[20];
        int age;
        int arr[3];
        StructPointerTest* next;
    }StructPointerTest, *StructPointer; 
    
    // 重要,因为使用g++编译时函数名会改变,比方print_msg(const char*)
    // 会编译成函数名 print_msg_char,这会导致python调用这个函数的时候
    // 找不到对应的函数名,只有加了 extern "C",才会以C语言的方式进行
    // 编译,这样不会改变函数名字
    extern "C" {  
        TestLib obj;  
        void display() {  
            obj.display();   
        }  
        void display_int() {  
            obj.display(2);   
        }
        void print_int_lst(const int* l, const int size) {
            cout << l[size-1] << endl;
        }
        void change_int_lst(int* l, const int size) {
            l[size-1] = 100;
        }
        void print(const char* s) {  
            cout << s << endl; 
        }
        float returnfloat(){
            float i=1;
            return i;
        }
        double returndouble(){
            double i=1;
            return i;
        }
        StructPointer returnstructure(){
            StructPointer p = (StructPointer)malloc(sizeof(StructPointerTest));
            StructPointer p2 = (StructPointer)malloc(sizeof(StructPointerTest));
            strcpy(p->name, "Joe");
            p->age = 20;
            p->arr[0] = 3;
            p->arr[1] = 5;
            p->arr[2] = 10;
            strcpy(p2->name, "John");
            p2->age = 40;
            p2->arr[0] = 30;
            p2->arr[1] = 50;
            p2->arr[2] = 100;
            p2->next = 0;
            p->next = p2;
    
            return p;
        }
    }
    

    Python

    #! /bin/Python3.8/bin/python3
    # _*_ encoding : utf-8 _*_
    
    import ctypes
    
    # |     ctypes     |     C                                   | Python                     |
    # | -------------- | --------------------------------------- | ---------------------------|
    # | c_char         | char                                    | 1-character string         |
    # | c_wchar        | wchar_t                                 | 1-character unicode string |
    # | c_byte         | char                                    | int/long                   |
    # | c_ubyte        | unsigned char                           | int/long                   |
    # | c_bool         | bool                                    | bool                       |
    # | c_short        | short                                   | int/long                   |
    # | c_ushort       | unsigned short                          | int/long                   |
    # | c_int          | int                                     | int/long                   |
    # | c_uint         | unsigned int                            | int/long                   |
    # | c_long         | long                                    | int/long                   |
    # | c_ulong        | unsigned long                           | int/long                   |
    # | c_longlong     | __int64 or longlong                     | int/long                   |
    # | c_ulonglong    | unsigned __int64 or unsigned long long  | int/long                   |
    # | c_float        | float                                   | float                      |
    # | c_double       | double                                  | float                      |
    # | c_longdouble   | long double float                       | float                      |
    # | c_char_p       | char *                                  | string or None             |
    # | c_wchar_p      | wchar_t *                               | unicode or None            |
    # | c_void_p       | void *                                  | int/long or None           |
    
    
    so = ctypes.cdll.LoadLibrary
    
    lib = so("./clib.so")
    
    print('display()')
    lib.display()
    
    print('
    display(100)')
    lib.display_int(100)
    
    print('
    display(100)')
    lib.display_int(100)
    
    # Python向clib传递字符串时需要decode,否则会只传递第一个字符(实测表现)
    print("
    Print Test")
    lib.print(b"Test")
    
    print("
    Print Test with encode")
    lib.print("Test".encode())
    
    print("
    Pass [1,2,3,4] and print the last element")
    ints = [1, 2, 3, 4]
    intArray4 = ctypes.c_int * len(ints)
    parameter_array = intArray4(*ints)
    lib.print_int_lst(parameter_array, len(ints))
    
    print("
    Pass [1,2,3,4] and change the last element as 100")
    ints = [1, 2, 3, 4]
    intArray = ctypes.c_int * len(ints)
    parameter_array = intArray(*ints)
    lib.change_int_lst(parameter_array, len(ints))
    print(parameter_array)
    for i in range(0, len(parameter_array)):
        print( parameter_array[i]+2, end=" ")
    print()
    
    print("
    Receive return")
    lib.returnfloat.restype = ctypes.c_float
    lib.returndouble.restype = ctypes.c_float
    print(isinstance(lib.returnfloat(), float))
    print(lib.returnfloat())
    print(lib.returnfloat()+1)
    print(lib.returndouble())
    
    print("
    Receive structure return")
    class StructPointer(ctypes.Structure):
        pass
    StructPointer._fields_ = [
        ("name", ctypes.c_char * 20),
        ("age", ctypes.c_int),
        ("arr", ctypes.c_int * 3),
        ("next", ctypes.POINTER(StructPointer))
    ]
    lib.returnstructure.restype = ctypes.POINTER(StructPointer)
    p = lib.returnstructure()
    print(p.contents.name.decode())
    print(p.contents.age)
    print(len(p.contents.arr))
    print(p.contents.arr)
    print(p.contents.arr[0])
    print(p.contents.arr[1])
    print(p.contents.arr[2])
    print(p.contents.next)
    print(p.contents.next.contents.name.decode())
    # 目前尚未找到python判断空指针的方法
    print(p.contents.next.contents.next)
    

    编译与调用

    g++ -shared clib.cpp -o clib.so -fPIC
    
    chmod +x caller.py
    ./caller.py
    
  • 相关阅读:
    乾颐堂7月HCIE、CCIE通过名单
    乾颐堂7月HCIE、CCIE通过名单
    乾颐堂7月HCIE、CCIE通过名单
    乾颐堂7月HCIE、CCIE通过名单
    Java实现文件压缩与解压[zip格式,gzip格式]
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/esctrionsit/p/15175965.html
Copyright © 2020-2023  润新知