#include #include #include // Добавили для работы с потоками #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include #include #include "include/SerialApp.h" #include // работает только после первой генерации #include "service.grpc.pb.h" static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error %d: %s\n", error, description); } bool initImGUI(GLFWwindow *&window) { glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) { return true; } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); window = glfwCreateWindow(1280, 720, "Serial App", nullptr, nullptr); if (window == nullptr) { return true; } glfwMakeContextCurrent(window); glfwSwapInterval(1); IMGUI_CHECKVERSION(); ImGui::CreateContext(); const ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 130"); return false; } // Простейшая реализация сервиса gRPC class MyServiceImpl final : public serial_sample::Greeter::Service { grpc::Status SayHello(grpc::ServerContext* context, const serial_sample::HelloRequest* request, serial_sample::HelloReply* reply) override { std::cout << request->name() << std::endl; reply->set_message("Hello, " + request->name() + "!"); return grpc::Status::OK; } }; int main(int, char**) { GLFWwindow *window; if (initImGUI(window)) { return 1; } SerialApp app; // frontend manager app.initialize(); // инициализация gRPC const std::string serverAddress("0.0.0.0:50051"); MyServiceImpl serviceImpl; grpc::ServerBuilder builder; builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials()); builder.RegisterService(&serviceImpl); std::unique_ptr gRPCServer(builder.BuildAndStart()); std::cout << "gRPC Server listening on " << serverAddress << std::endl; // сервер стартует в фоновом БЛОКИРУЮЩЕМ потоке std::thread gRPCThread([&gRPCServer] { gRPCServer->Wait(); }); // ========================================= // Главный цикл приложения (GUI поток) while (!glfwWindowShouldClose(window)) { glfwPollEvents(); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); app.renderUI(); if (app.isClosing()) { glfwSetWindowShouldClose(window, GLFW_TRUE); } ImGui::Render(); int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); glClearColor(0.45f, 0.55f, 0.60f, 1.00f); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } // выключение gRPC std::cout << "Shutting down gRPC server..." << std::endl; // Останавливаем сервер (это разблокирует метод Wait() в фоновом потоке) gRPCServer->Shutdown(); // Обязательно дожидаемся завершения фонового потока перед выходом из main if (gRPCThread.joinable()) { gRPCThread.join(); } std::cout << "gRPC server thread joined." << std::endl; // ========================================= ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); return 0; }