diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Makefile.am | 4 | ||||
-rw-r--r-- | examples/meson.build | 1 | ||||
-rw-r--r-- | examples/subprocess/main.cc | 114 |
3 files changed, 119 insertions, 0 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am index a32cfb84..4de7e4e3 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -33,6 +33,7 @@ check_PROGRAMS = \ properties/example \ regex/example \ settings/settings \ + subprocess/example \ thread/dispatcher \ thread/dispatcher2 @@ -85,6 +86,9 @@ network_socket_server_LDADD = $(giomm_ldadd) settings_settings_SOURCES = settings/settings.cc settings_settings_LDADD = $(giomm_ldadd) +subprocess_example_SOURCES = subprocess/main.cc +subprocess_example_LDADD = $(giomm_ldadd) + dist_noinst_DATA = settings/org.gtkmm.demo.gschema.xml CLEANFILES = settings/gschemas.compiled diff --git a/examples/meson.build b/examples/meson.build index f2c47417..04a7608a 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -17,6 +17,7 @@ examples = [ [['properties'], 'example', ['properties_example.cc'], false], [['regex'], 'example', ['main.cc'], false], [['settings'], 'settings', ['settings.cc', 'org.gtkmm.demo.gschema.xml'], true], + [['subprocess'], 'example', ['main.cc'], true], [['thread'], 'dispatcher', ['dispatcher.cc'], false], [['thread'], 'dispatcher2', ['dispatcher2.cc'], false], ] 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; +} |