In ubuntu, based on the Qt platform, call the python file and cross-compile it to the embedded linux development board to run

1. Brief introduction

1.1 Clear goals

Because it needs to be run on an embedded Linux development board, the x86_64 platform files need to be cross-compiled into arm architecture files through cross-compilation. The main thing here is to cross-compile the python source code and its dependent libraries, and then cross-compile on the QT platform of ubuntu to build an executable file that uses the python language and can run on the embedded Linux platform.

1.2 python version and its background

  1. Cross-compilation tool chain: gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf
  2. ubuntu platform:ubuntu18.04.1 64bit
  3. python version: python3.6.9
  4. Embedded linux development board kernel: NXP CORTEX-A7 IMX6ULL

1.3 Steps

  1. First cross-compile the python source code and its dependent libraries
  2. Ported to linux development board
  3. Writing demo verification on ubuntu's Qt platform

2. Cross-compile python source code and its dependent libraries

2.1 Compilation steps

  1. Cross-compile the openssl library, which is likely to be used by most other libraries
  2. Cross-compile the zlib library, which is a necessary dependent library for python source code installation
  3. Cross compile libffi library
  4. Cross-compile python source code.
    Here is a Baidu network disk link. You can download the relevant libraries from the official website, or you can get them directly from here:
    Link: https://pan.baidu.com/s/1mui3Vw8FfxnMUFSjFZhItA
    Extraction code: pwev

2.2 Cross-compile openssl

  1. Download openssl, https://www.openssl.org/source/ . The version I am using here is openssl1.1.1.
    (Note: For the convenience of management, all downloaded source codes are placed in /home/book/pyarm/zlibarm/)
  2. Unzip: tar -xzvf openssl-1.1.1.tar.gz
  3. cd openssl-1.1.1
  4. Configure the compilation environment: ./Configure no-asm shared no-async linux-generic32 --prefix=/home/book/pyarm/opensslarm --cross-compile-prefix=arm-linux-gnueabihf- no-asm in the cross-compilation
    process Assembly code is not used to speed up the compilation process;
    shared generates a dynamic link library.
    no-async The cross-compilation tool chain does not provide the GNU C ucontext library
    –prefix= installation path (after make and make install, openssl-related include and lib files are in this directory. You can choose the installation directory by yourself) –cross-
    compile -prefix= cross-compilation tool
    linux-generic32 means cross-compiling to a 32-bit operating system
  5. make
  6. make install

2.3 Cross-compile zlib

  1. Download zlib, http://zlib.net/ . The version I am using here is 1.2.11.
  2. Unzip: tar -xzvf zlib-1.2.11.tar.gz
  3. cd zlib-1.2.11
  4. Set the compiler: export CC=arm-linux-gnueabihf-gcc (because there is no option to configure the compiler in zlib's configure, so set the environment variable here)
  5. Configure the compilation environment: ./configure --prefix=/home/book/pyarm/zlibarm --enable-shared
  6. make
  7. make install

2.4 Cross-compile libffi

  1. Download libffi, https://sourceware.org/libffi/ . The version I am using here is 3.2.1
  2. Unzip: tar xvzf libffi-3.2.1.tar.gz
  3. cd libffi-3.2.1
  4. 配置编译环境:./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf --build=x86_64-linux-gnu target=arm-linux-gnueabihf --enable-shared --prefix=/home/book/pyarm/libffiarm
  5. make
  6. make install

2.5 Cross-compile python

  1. Download python, https://www.python.org/downloads/source/ . The version I am using here is 3.6.9

  2. Unzip: tar xvf Python-3.6.9.tgz

  3. cd Python-3.6.9

  4. mkdir /home/book/arm-python (because python compilation depends on the above library, so add a directory here, and the include and lib compiled above are moved to this directory)

  5. Copy the header files and link libraries of the relevant libraries compiled above to /home/book/arm-python cp -rfp /
    home/book/pyarm/zlibarm/* /home/book/arm-python cp
    -rfp /home/ book/pyarm/libffiarm/* /home/book/arm-python
    cp -rfp /home/book/pyarm/opensslarm/* /home/book/arm-python

  6. 设置CFLAGS:CFLAGS=“-I /home/book/arm-python -I /home/book/arm-python/include/python3.6m -L /home/book/arm-python/lib”

  7. Set LDFLAGS: LDFLAGS="-L /home/book/arm-python/lib"

  8. vi Modules/Setup.dist, modify the header files and library files of the relevant libraries inside.
    Insert image description here
    Insert image description here

    Note: As you can see from the picture above, the path to the library we set is an absolute path, so when we package the compiled files to the development board later, they must also be placed in /home/book/arm-python of the development board. directory (if not, you can create it yourself)
    (The reason is: The Python virtual environment will record the absolute path of the Python compiler ; therefore, when running the Python virtual environment on other hosts, the virtual environment will still look for the Python compiler under this absolute path. .So the same directory must be created on the development board, otherwise errors such as files and modules not found will occur)

  9. ./configure CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ AR=arm-linux-gnueabihf-ar RANLIB=arm-linux-gnueabihf-ranlib --host=arm-linux-gnueabihf --build=x86_64-linux-gnu --target=arm-linux-gnueabihf --disable-ipv6 ac_cv_file__dev_ptmx=yes ac_cv_file__dev_ptc=yes --prefix=/home/book/arm-python --enable-shared --without-ensurepip

  10. make

  11. make install

3. Transplant to linux development board

  1. Compress the arm-python directory: cd /home/book tar cvf arm-python.tar arm-python
  2. Transfer arm-python.tar to the /home/book directory of the development board through tools such as FileZilla
  3. Unzip: tar xvf arm-python.tar
    Summary: After the above steps, the python transplant has been completed. You can also cd /home/book/arm-python/bin here, and then ./python3 to enter the python interface programming, and use exit() to exit. Python interface, return to the command line.

4. Write demo verification on ubuntu’s Qt platform

  1. Create a new project in Qt-----The template I chose here is Application (Qt)-----name: py_test, and the creation path is /home/book/QT/my_qt/qt_python------behind Several steps are defaulted -----Finally check the cross-compilation tool chain----finished.
  2. Create a new file—select Python, Python File----name: test_pyfile.py, the path does not need to be modified----complete. (After creation, you can see the test_pyfile.py file in Other files of the project)
  3. Add the following code to the test_pyfile.py file: (The main function is to pass in a string through parameter a, and then return a concatenated string b)
def testpyfile(a):
    b = a+'jiayou'
    return b
# 这里必须空两行:
# python编码规范:类与类,类与函数,函数与函数之间空两行)
print(testpyfile("111"))
  1. Import python-related library files and header files in the .pro file
INCLUDEPATH += \
               -I /home/book/arm-python/include/python3.6m/ \
               -I /home/book/arm-python/include  \
               -I /home/book/arm-python/include/openssl

LIBS += \
        -L /home/book/arm-python/lib/ -lpython3.6m  \
        -L /home/book/arm-python/lib/ -lssl   \
        -L /home/book/arm-python/lib/ -lcrypto   \
        -L /home/book/arm-python/lib/ -lz   \
  1. Add the following code in the main function:
#include "mainwindow.h"

#include <QApplication>

#include "Python.h"   //引入python头文件
#include <QDebug>

int main(int argc, char *argv[])
{
    
    
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    Py_Initialize();   // 初始化Python

    PyObject *pModule = nullptr;
    PyObject *pLoadFunc = nullptr;
    PyObject *pArgs = nullptr;
    PyObject *pReturn = nullptr;
    PyObject *str = nullptr;

    const char *bytes = nullptr;

    if(!Py_IsInitialized())
    {
    
    
        qDebug()<<"inititalize failed";
        return -1;
    }
    else
        qDebug()<<"inititalize success";

    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('/home/book/QT/my_qt/qt_python/py_test')");

    pModule = PyImport_ImportModule("test_pyfile");
    if(!pModule)
    {
    
    
        PyErr_Print();
        qDebug()<<"not loaded module";
        return -1;
    }
    else
        qDebug()<<"load module success";

    pLoadFunc = PyObject_GetAttrString(pModule, "testpyfile");
    if(!pLoadFunc)
    {
    
    
        PyErr_Print();
        qDebug()<<"not loaded pLoadFunc";
        return -1;
    }
    else
        qDebug()<<"load pLoadFunc success";

    pArgs = PyTuple_New(1);
    PyTuple_SetItem(pArgs, 0 , Py_BuildValue("s", "xuheqing"));
    pReturn = PyObject_CallObject(pLoadFunc, pArgs);
    if(!pReturn)
    {
    
    
        qDebug()<<"no return value";
        return -1;
    }

    str = PyObject_Str(pReturn);

    bytes = PyUnicode_AsUTF8(str);

    qDebug()<<bytes;

	Py_Finalize();// 关闭 Python 脚本解释器

    return a.exec();
}

Note: The absolute path is used in PyRun_SimpleString("sys.path.append('/home/book/QT/my_qt/qt_python/py_test')") to add the .py file we wrote ourselves, so we need to put the file in In the /home/book/QT/my_qt/qt_python/py_test directory of the development board (if not, you can create it yourself). Otherwise, when the development board is running, there will be an error that the file module cannot be found! ! !

  1. Before building, sudo vi /home/book/arm-python/include/python3.6m/object.h and modify it as shown below. (Because slots are defined as keys in QT, and slots are used as variables in python3, there will be conflicts during compilation.)
    Insert image description here

  2. Select the cross-compilation tool, then right-click the py_test project and click Build to get the program py_test that can run on the arm architecture.
    Insert image description here
    Insert image description here

  3. Transfer the py_test file to the /mnt directory of the development board through tools such as FileZilla. First chmod +x py_test, add executable operations to py_test, and then ./py_test. At this time, you will find an error:
    ./py_test: error while loading shared libraries: libpython3.6m.so.1.0: cannot open shared object file: Norectory
    Solution :
    ① First use the command echo $PATHto display the current PATH environment variable. My environment variable is / bin:/sbin:/usr/bin:usr/sbin. When we execute the program, the shell automatically searches these paths for the program based on the value of the PATH variable. So you can export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/book/arm-python/libadd the path to the python related library and you can execute it.
    (Note: This is only one of the methods, and it is only a temporary modification. After restarting the development board, the environment variable needs to be reset)
    ② vi /etc/profile. Added at the end of the file export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/book/arm-python/lib. Then restart the development board . The environment variables in /etc/profile are valid for all users and are run when the system starts. This is a way for environment variables to be permanently valid.

  4. operation result
    Insert image description here

5. Reference document links

  1. Cross compilation of python and third-party libraries
  2. QT+python hybrid programming in ubuntu environment
  3. Py_Initialize: unable to load the file system codec error occurs when calling Python script using virtual Python environment C++

Guess you like

Origin blog.csdn.net/m0_43443861/article/details/127907530