Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to deploy Qt application with external libraries

How to deploy Qt application with external libraries

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 2 Posters 679 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jonah765
    wrote on last edited by jonah765
    #1

    Hello, So ive built my Qt application and it uses the Python C API, which I statically link. In my .pro file. I Include it in my project as so:

    LIBS += -L"C:/python/libs" -lpython38
    
    INCLUDEPATH += C:/python/include/
    
    DEPENDPATH += C:/python/include/
    

    linking to a local directory on my computer. I then #include "Python.h" in one of my header files as usual - no problems.

    This works fine, but when it comes to deploying the application, I receive the error from windows:

    The code execution cannot proceed because python38.dll was not found. Reinstalling the program may fix this problem.
    

    Now, I dont understand why I got this error because I thought all the required Python libraries would be compiled into the .exe file since it was statically linked.

    Anyway, I add the python38.dll to the directory where my .exe is located, As required, and the program (.exe file) starts fine. However, when it gets to the part where it actually has to call the python code, the application just crashes.

    Any suggestion towards how I may fix this? Thank you.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      What do you do in that script ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      J 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi,

        What do you do in that script ?

        J Offline
        J Offline
        jonah765
        wrote on last edited by
        #3

        @SGaist In the python script you mean? It has a couple functions which sends request to a raspberry pi server. Here is how the python code is called within my Qt Application:

                Py_Initialize();
        
                PyObject* sys = PyImport_ImportModule( "sys" );
                PyObject* sys_path = PyObject_GetAttrString( sys, "path" );
                PyObject* folder_path = PyUnicode_FromString( "." );
                PyList_Append( sys_path, folder_path );
        
                PyObject *pName = PyUnicode_FromString("client");
                PyObject *pModule = PyImport_Import(pName);
        
                Py_DECREF(pName);
        
                PyObject* pFunc_send = PyObject_GetAttrString(pModule, (char*)"send_string");
                PyObject* pFunc_connect = PyObject_GetAttrString(pModule, (char*)"connect_to_server");
        
                if ((pFunc_send && PyCallable_Check(pFunc_send)) && (pFunc_connect && PyCallable_Check(pFunc_send)))
                    {
                        PyObject* pResult_connect = PyObject_CallObject(pFunc_connect, NULL);
        
                        const int connection_result = PyLong_AsLong(pResult_connect);
        
                        if(connection_result)
                        {
                            for(auto question : cachedQuestions)
                            {
                                const char* args[2] = {question.first.c_str(), question.second.c_str()};
        
                                PyObject* pArgs_send = PyTuple_New(2);
        
                                for(int i = 0; i < 2; ++i)
                                {
                                    PyObject* pValue = PyUnicode_FromString(args[i]);
                                    if (!pValue) {
                                        Py_DECREF(pArgs_send);
                                        Py_DECREF(pModule);
                                        fprintf(stderr, "Cannot convert argument\n");
                                    }
                                    PyTuple_SetItem(pArgs_send, i, pValue);
                                }
        
                                //send the question and capture the server response
                                PyObject* pResult = PyObject_CallObject(pFunc_send, pArgs_send);
        
                                const std::string result = _PyUnicode_AsString(pResult);
        
                                Py_DECREF(pArgs_send);
                                Py_DECREF(pResult);
        
                                if(result == "data_error" && (POTWParams["new_playlist"] == "False"))
                                {
                                    generateNewPopup("ERROR 1\n\n"
                                                     "there was an error in trasmitting your data to the    server\n"
                                                     "make sure your spotify playlist is of the form: https://open.spotify.com/playlist/________\n"
                                                     "please try again");
        
                                    bool result = disconnect_server(pFunc_send);
        
                                    if(!result)
                                    {
                                        generateNewPopup("ERROR 2\n\n"
                                                         "there was an error when attempting to disconnect from the server\n"
                                                         "trying again ...");
        
                                        disconnect_server(pFunc_send);
        
                                        Py_DECREF(pFunc_send);
                                        Py_DECREF(pFunc_connect);
                                        Py_DECREF(pModule);
                                    }
        
                                    return;
                                }
                            }
                        }
                        bool disconnect_result = disconnect_server(pFunc_send);
        
                        if(disconnect_result)
                            generateNewPopup("SUCCESS\n\n"
                                             "A new POTW is now underway :)\n"
                                             "You may now quit the program");
                    }
                    else
                    {
                        generateNewPopup("ERROR\n\n"
                                         "Could not call send function"
                                         "A file may have been moved or destroyed")
        ;            }
        
                    Py_DECREF(pFunc_send);
                    Py_DECREF(pFunc_connect);
                    Py_DECREF(pModule);
        
               // Finish the Python Interpreter
                Py_Finalize();
            }
            else{
                generateNewPopup("ERROR\n\n"
                                 "you did not fill in all the necessary fields.\n "
                                  "Your request was not transmitted to the server. \n"
                                  "Please try again \n");
            }
        

        you dont have to read it all, but just so you understand how im using the API I gave it for reference.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Why not use QNetworkAccessManager rather than embedding python ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          J 1 Reply Last reply
          1
          • SGaistS SGaist

            Why not use QNetworkAccessManager rather than embedding python ?

            J Offline
            J Offline
            jonah765
            wrote on last edited by
            #5

            @SGaist I could, but that would probably require me to install Qt on my target machine (im not even sure it has enough storage for that), and, the server needs to interact with a host of web APIs so it would have to switch from c++ to python at some point, since C++ is often not supported in those use cases. I do take your point though, and will probably resort to this if i cant find a solution for my current problems.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Why would you need to do that ?
              QNetworkAccessManager just does standard http requests. The backend can be whatever you want.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • J Offline
                J Offline
                jonah765
                wrote on last edited by jonah765
                #7

                I think you're right, it might be easier just to switch to an all Qt implementation. If I just need strings encoded in utf-8 format to a specific Port at a specific IP address, is QNetworkAccessManager the best tool for the job?

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  What should your request look like ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    jonah765
                    wrote on last edited by jonah765
                    #9

                    essentially the message being sent is built up as:

                    [length of opcode (in bytes)] - [length of message (in byes)] - [opcode] - [message]

                    where each section above is a utf-8 encoded strings.

                    My original python code was:

                    HEADER = 256 #header length(bytes)
                    OPCODE = 4
                    PORT = #####REDACTED_FOR_PRIVACY#####
                    FORMAT = 'utf-8'
                    DISCONNECT_MESSAGE = "!DISCONNECT"
                    SERVER = #####REDACTED_FOR_PRIVACY#####
                    ADDR = (SERVER, PORT)
                    
                    class Opcode (str, Enum):
                        WEEK:                 str = "1"
                        EMAIL:                str = "2"
                        COMPETITION_DURATION: str = "3"
                        SPOTIFY:              str = "5"
                        SUBMISSION_DURATION:  str = "6"
                        RANKING_DURATION:     str = "7"
                        DISCONNECT:           str = "8"
                        NEW_PLAYLIST:         str = "9"
                        NUM_PARTICIPANTS:     str = "10"
                        NAME_QUESTION:        str = "11"
                        BONUS_QUESTION:       str = "12"
                    
                    def connect_to_server():
                        global client
                        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                        client.connect(ADDR)
                        
                    def send(opcode, msg):
                            
                        message= msg.encode(FORMAT) #convert the message to byte format
                        op = opcode.encode(FORMAT)
                    
                        msg_length = len(message) #length of message 
                        msg_send_length = str(msg_length).encode(FORMAT) #convert the length of the message to byte format
                        
                        op_length = len(op)
                        op_send_length = str(op_length).encode(FORMAT)
                        
                        # Pad out the length to 64 bytes and the opcode to 4 bytes
                        msg_send_length += b' ' * (HEADER - len(msg_send_length)) 
                        op_send_length  += b' ' * (OPCODE - len(op_send_length)) 
                        
                        client.send(msg_send_length)
                        client.send(op_send_length)
                        client.send(op)
                        client.send(message)
                    
                        return client.recv(2048).decode(FORMAT)
                    
                    
                    send(Opcode.EMAIL, "example@gmail.com")
                    send(Opcode.WEEK, "12")
                    send(Opcode.COMPETITION_DURATION, "7")
                    send(Opcode.SPOTIFY, "https://open.spotify.com/playlist/cyt67ryic657bi")
                    
                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved