diff options
Diffstat (limited to 'examples/subprocess/main.cc')
-rw-r--r-- | examples/subprocess/main.cc | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/examples/subprocess/main.cc b/examples/subprocess/main.cc new file mode 100644 index 00000000..f72526ee --- /dev/null +++ b/examples/subprocess/main.cc @@ -0,0 +1,114 @@ +/* Copyright (C) 2023 The gtkmm Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <giomm.h> +#include <iostream> + +namespace +{ +int finish_pending = 0; + +void on_communicate_finished(Glib::RefPtr<Gio::AsyncResult>& result, + const Glib::RefPtr<Gio::Subprocess>& subprocess, const Glib::ustring& heading) +{ + try + { + std::cout << "\n" << heading << "\n"; + auto [stdout_buf, stderr_buf] = subprocess->communicate_utf8_finish(result); + std::cout << "stdout_buf: " << stdout_buf << "\n" + << "stderr_buf: " << stderr_buf << "\n"; + } + catch (const Glib::Error& error) + { + std::cerr << "on_communicate_finished(), Glib::Error: " << error.what() << std::endl; + } + catch (const std::exception& error) + { + std::cerr << "on_communicate_finished(), std::exception: " << error.what() << std::endl; + } + --finish_pending; +} +} // anonymous namespace + +int main(int argc, char** argv) +{ + Gio::init(); + + if (argc < 3) + { + std::cerr << "Usage: " << argv[0] << " input-data command [arguments]...\n"; + return 1; + } + + // Three character encodings can be involved: + // 1. The encoding in the user's preferred locale. + // 2. The filename encoding, used by GLib. + // 3. UTF-8. + // The encoding used in argv is determined by the operating system. + // It's assumed to be the encoding in the user's preferred locale, + // which is also the C and C++ global locale. See the documentation of + // Glib::set_init_to_users_preferred_locale(). + try + { + const auto stdin_buf = Glib::locale_to_utf8(argv[1]); + + std::vector<std::string> arg_vector; + for (int i = 2; i < argc; ++i) + arg_vector.push_back(Glib::filename_from_utf8(Glib::locale_to_utf8(argv[i]))); + + Gio::Subprocess::Flags flags = + Gio::Subprocess::Flags::STDOUT_PIPE | Gio::Subprocess::Flags::STDERR_PIPE; + if (!stdin_buf.empty()) + flags |= Gio::Subprocess::Flags::STDIN_PIPE; + + // This example would be easier with the synchronous communicate_utf8(). + + // Without SubprocessLauncher. + auto subprocess = Gio::Subprocess::create(arg_vector, flags); + ++finish_pending; + subprocess->communicate_utf8_async(stdin_buf, + [&subprocess](Glib::RefPtr<Gio::AsyncResult>& result) + { + on_communicate_finished(result, subprocess, "Without SubprocessLauncher"); + }); + + // With SubprocessLauncher. + auto launcher = Gio::SubprocessLauncher::create(flags); + auto spawned_subprocess = launcher->spawn(arg_vector); + ++finish_pending; + spawned_subprocess->communicate_utf8_async(stdin_buf, + [&spawned_subprocess](Glib::RefPtr<Gio::AsyncResult>& result) + { + on_communicate_finished(result, spawned_subprocess, "With SubprocessLauncher"); + }); + } + catch (const Glib::Error& error) + { + std::cerr << "Glib::Error: " << error.what() << std::endl; + return 1; + } + catch (const std::exception& error) + { + std::cerr << "std::exception: " << error.what() << std::endl; + return 1; + } + + // Wait for on_communicate_finished() to finish. + auto main_context = Glib::MainContext::get_thread_default(); + while (finish_pending > 0) + main_context->iteration(true); + return 0; +} |