Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Unsolved How to deploy Qt application with external libraries

    General and Desktop
    2
    9
    212
    Loading More Posts
    • 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
      jonah765 last edited by jonah765

      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 Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        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 Reply Quote 0
        • J
          jonah765 @SGaist last edited by

          @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 Reply Quote 0
          • SGaist
            SGaist Lifetime Qt Champion last edited by

            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 Reply Quote 1
            • J
              jonah765 @SGaist last edited by

              @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 Reply Quote 0
              • SGaist
                SGaist Lifetime Qt Champion last edited by

                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 Reply Quote 1
                • J
                  jonah765 last edited by jonah765

                  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 Reply Quote 0
                  • SGaist
                    SGaist Lifetime Qt Champion last edited by

                    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 Reply Quote 0
                    • J
                      jonah765 last edited by jonah765

                      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 Reply Quote 0
                      • First post
                        Last post