Python呼び出しダイナミックリンクライブラリチュートリアル(return/ポインタ)

15164 ワード

文書ディレクトリ
  • 前言
  • C言語実装部
  • Pythonテスト部分コード
  • 前言
    現在、Pythonは自動車電子業界でますます人気を集めており、特に各家庭でAUTOSARに加入した後、その煩雑な開発プロセスと関連ツールがまだ完備していない現状のため、一連のツール化、自動化、ツールチェーン化の仕事を行う必要があり、Pythonはここ数年の怒りの言語として、加えて、ネットワーク上にはすでに多くの自動車電子開発に必要な車輪(例えばcanmatrixがdbcをexcelにワンタッチで変換できるなど)が存在し、身近な同僚や異なる会社の同業者が、pythonを主力ツールとして言語を開発することを約束している.
    本チュートリアルでは、このシナリオに基づいて、C言語で秘密保持が必要なコアアルゴリズムを作成し、Pythonで対応するテストプログラムを開発し、2つの部分の共同呼び出しを行う案を紹介します.
    C言語実装部
  • testDll.c
  • /*-----------------------------------------------------------------------------
    /*   Testing file for dll and python combine
    /*  
    /*   File         : testDll.c
    /*   Complier     : gcc  Ver. > 4.9
    /*   Author       : Tomato 
    /*   Time         : 2019/8/23
    /*   Instructions : New file                                           - 0.1            
    /*                 
    /*---------------------------------------------------------------------------*/
    
    /* Incluce files */
    #include "testDll.h"
    
    /* Parameters */
    
    /* Function Declation */
    void __TestFuncAry(uint8 * arrayHead, uint8 arraySize);
    uint8 __TestFuncRtn(uint8 argv1, uint8 argv2);
    
    void main()
    {
        /* */
    }
    
    /* Function start----------------------------------------------------------- */
    void __TestFuncAry(uint8 * arrayHead, uint8 arraySize)
    {
        for (uint8 i = 0u; i < arraySize; i++)
        {
            arrayHead[i] ++;
        }
    }
    
    /* End of function---------------------------------------------------------- */
    
    /* Function start----------------------------------------------------------- */
    uint8 __TestFuncRtn(uint8 argv1, uint8 argv2)
    {
        uint8 temp_vle = 0u;
        temp_vle = argv1 + argv2;
        return temp_vle;
    }
    
    /* End of function---------------------------------------------------------- */
    
    
  • testDll.h
  • /*-----------------------------------------------------------------------------
    /*   Testing file for dll and python combine
    /*  
    /*   File         : testDll.h
    /*   Complier     : gcc  Ver. > 4.9
    /*   Author       : Tomato
    /*   Time         : 2019/8/23
    /*   Instructions : New file                                           - 0.1            
    /*                 
    /*---------------------------------------------------------------------------*/
    
    #ifndef _TESTDLL_H
    #define _TESTDLL_H
    
    /* Alies type define */
    typedef signed char int8_T;
    typedef unsigned char uint8_T;
    typedef short int16_T;
    typedef unsigned short uint16_T;
    typedef int int32_T;
    typedef unsigned int uint32_T;
    typedef float real32_T;
    typedef double real64_T;
    typedef double real_T;
    typedef double time_T;
    typedef unsigned char boolean_T;
    
    /* AUTOSAR Base to Platform types mapping */
    typedef boolean_T boolean;
    typedef int16_T sint16;
    typedef int32_T sint32;
    typedef int8_T sint8;
    typedef uint16_T uint16;
    typedef uint32_T uint32;
    typedef uint8_T uint8;
    typedef real32_T float32;
    typedef real_T float64;
    
    /* Function Declation */
    extern void __TestFuncAry(uint8 * arrayHead, uint8 arraySize);
    extern uint8 __TestFuncRtn(uint8 argv1, uint8 argv2);
    
    #endif
    

    この例は1つのみ存在する.cファイルは、実際のアプリケーションシーンには多くのソースファイルが存在するので、cを動的リンクライブラリにコンパイルして統一呼び出しを行うのが最善です.
    この例では、コンピュータがgccコンパイラをインストールすることを前提として、ダイナミックリンクライブラリのコンパイルに次のコマンドを使用します.
  • windows
  • gcc -fPIC -shared testDll.c -o testDll.dll
    
  • linux
  • gcc -fPIC -shared testDll.c -o testDll.so
    

    複数のソースファイルの場合はmakefileを作成できます.
    Pythonテスト部分コード
    なお、cやPythonではデータ型が通用しないため、配列(アドレスが連続し、各要素のデータ型が統一されている)などの複雑なデータ型を使用する場合は変換などの前処理を先に行う必要がある.
    このチュートリアルではnumpyモジュールを使用してデータ型変換を行います.プログラムの例は次のとおりです.
  • Python
  • #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    # -----------------------------------------------------------------------------
    #    Testing file for dll/so and python combine
    #   
    #    File         : testPyWithC.py
    #    Author       : Tomato
    #    Time         : 2019/8/23
    #    Instructions : New file                                           - 0.1            
    #                  
    # -----------------------------------------------------------------------------
    
    # Import files
    from ctypes import *
    import numpy as np
    
    # load the shared object file ,*.so(linux) or *.dll(windows)
    testLib = CDLL('./testDll.so')
    
    # Testing normal input, datatype implict truned
    testRtn = testLib.__TestFuncRtn(15,20)
    print(testRtn)
    
    # test array ,should convert datatype first------------------------------------
    strInput = input("Please input testing array eg.50 60: ")
    # Turn string input to number
    input_list = strInput.split(' ')
    num_list = list()
    for data in input_list:
        num_list.append(int(data))
    
    # Judge generate array's memmroy whether is continues
    #     numpy   uint8    ,          ,              -  !
    testArray = np.asarray(num_list, dtype=np.uint8).reshape(-1)
    if not testArray.flags['C_CONTIGUOUS']:
        testArray = testArray.ascontiguous(testArray, dtype=testArray.dtype)
    
    # Turn to ctypes pointer
    #    ctypes  ,   c    uint8 *
    testArrayPtr = cast(testArray.ctypes.data, POINTER(c_uint8))
    
    # Get array length
    aryLen = len(num_list)
    
    # Testing c function with pointer used
    testLib.__TestFuncAry(testArrayPtr,aryLen)
    
    for i in range(aryLen):
        print(testArrayPtr[i])
    

    実行後テスト入力11 12では、以下の結果が得られ、コンビネーションコールが成功したことを証明します.
    35
    Please input testing array eg.50 60: 11 12
    12
    13