我需要用 C++ 在 Linux PC 上注册蓝牙服务,到目前为止,我可以用这样的代码来做到这一点:(从这里截取和缩短)。
#include <cstdio>
#include <gio/gio.h>
#include <glib.h>
#define SERIAL_PORT_PROFILE_UUID "00001101-0000-1000-8000-00805F9B34FB"
#define CUSTOM_UUID "22222222-2222-2222-2222-222222222222" //"E62C4DCA-9ABC-11E5-8994-FEFF819CDC9F"
int register_profile(GDBusProxy *proxy){
GVariant *profile;
GVariantBuilder profile_builder;
GError *error = NULL;
printf("register_profile called!\n");
g_variant_builder_init(&profile_builder, G_VARIANT_TYPE("(osa{sv})"));
if (g_variant_is_object_path("/org/bluez/customprofile")) {
printf("object path is good!\n");
}
g_variant_builder_add (&profile_builder, "o",
"/org/bluez/customprofile");
g_variant_builder_add (&profile_builder, "s", SERIAL_PORT_PROFILE_UUID);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "Channel");
g_variant_builder_add (&profile_builder, "v", g_variant_new_uint16(22));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "Service");
g_variant_builder_add (&profile_builder, "v", g_variant_new_string(CUSTOM_UUID));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "Name");
g_variant_builder_add (&profile_builder, "v", g_variant_new_string("Custom Serial Port"));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "Role");
g_variant_builder_add (&profile_builder, "v", g_variant_new_string("server"));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "RequireAuthentication");
g_variant_builder_add (&profile_builder, "v", g_variant_new_boolean(FALSE));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "RequireAuthorization");
g_variant_builder_add (&profile_builder, "v", g_variant_new_boolean(FALSE));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "AutoConnect");
g_variant_builder_add (&profile_builder, "v", g_variant_new_boolean(TRUE));
g_variant_builder_close(&profile_builder);
g_variant_builder_close(&profile_builder);
profile = g_variant_builder_end(&profile_builder);
GVariant * ret = g_dbus_proxy_call_sync (proxy,
"RegisterProfile",
profile,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
g_assert_no_error(error);
if(ret != NULL && error==NULL){
return 0;
} else {
return 1;
}
}
void init_server()
{
GDBusProxy *proxy;
GDBusConnection *conn;
GError *error = nullptr;
GMainLoop *loop = g_main_loop_new (nullptr, false);
conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, nullptr, &error);
g_assert_no_error (error);
proxy = g_dbus_proxy_new_sync (conn,
G_DBUS_PROXY_FLAGS_NONE,
nullptr,/* GDBusInterfaceInfo */
"org.bluez",/* name */
"/org/bluez",/* object path */
"org.bluez.ProfileManager1",/* interface */
nullptr,/* GCancellable */
&error);
g_assert_no_error (error);
error=nullptr;
if (register_profile (proxy)) {
printf("profile register failed\n");
return;
}
printf("SPP profile registered");
g_main_loop_run (loop);
g_object_unref (proxy);
g_object_unref (conn);
}
int main(int argc, const char** argv) {
init_server();
}
Everyting 效果很好,我可以在 bluetoothctl 或 sdptool 浏览器中看到该服务(来自其他 PC)。
问题是:我想在注册后继续执行程序,但是我不明白如何在g_main_loop_run (loop);. 如果我只是删除对主循环(GMainLoop *loop = g_main_loop_new (nullptr, false);和以前的)的所有调用,那么服务将不再出现在 bluetoothctl/sdptool 浏览中。如果我在g_main_loop_quit(loop);之后添加行g_main_loop_run (loop);,它也不会被执行,因为循环仍在运行。那我该怎么办?
我已经阅读了 GMainLoop 和 GDBusProxy 描述(GMainLoop,GDBusProxy),但它并没有太大帮助。我也看到了这个问题,但是那里列出的代码不完整,我不确定我应该从那里拿什么,不应该拿什么。