summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile.am4
-rw-r--r--examples/meson.build1
-rw-r--r--examples/subprocess/main.cc114
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;
+}