编译还是报如下错误: root@ZGI:/userdata# root@ZGI:/userdata# gcc -o pimow_bt pimow_bt.c `pkg-config --cflags --libs glib-2.0 gio-2.0` pimow_bt.c: In function ‘handle_char_read’: pimow_bt.c:23:12: error: too many arguments to function ‘g_variant_new_bytestring’ 23 | return g_variant_new_bytestring("PimowResponse", 13); // 包括null终止符 | ^~~~~~~~~~~~~~~~~~~~~~~~ In file included from /usr/include/glib-2.0/glib/gmessages.h:36, from /usr/include/glib-2.0/glib.h:62, from /usr/include/glib-2.0/gobject/gbinding.h:28, from /usr/include/glib-2.0/glib-object.h:22, from /usr/include/glib-2.0/gio/gioenums.h:28, from /usr/include/glib-2.0/gio/giotypes.h:28, from /usr/include/glib-2.0/gio/gio.h:26, from pimow_bt.c:1: /usr/include/glib-2.0/glib/gvariant.h:124:33: note: declared here 124 | GVariant * g_variant_new_bytestring (const gchar *string); | ^~~~~~~~~~~~~~~~~~~~~~~~
时间: 2025-08-30 08:54:29 AIGC 浏览: 20
<think>
我们遇到了关于`g_variant_new_bytestring`函数的错误,提示参数过多。根据GLib文档,`g_variant_new_bytestring`只接受一个参数,即指向字节字符串的指针。这个函数会创建一个新的字节字符串类型的GVariant,字符串以null结尾,因此我们不需要传递长度。
在之前的代码中,我们错误地传递了两个参数:字符串和长度。实际上,这个函数只需要一个以null结尾的字符串。
让我们修正这个错误:
1. 在`handle_char_read`函数中,将返回语句改为:
```c
return g_variant_new_bytestring("PimowResponse");
```
2. 同时,在`handle_char_write`函数中,我们使用`g_variant_get_string`来获取字符串,但注意写入操作中,我们定义的特性类型是`ay`(字节数组),而`g_variant_get_string`适用于字符串类型(`s`)。因此,我们需要统一数据类型。
有两种解决方案:
a) 修改特性类型为字符串(`s`),这样我们可以使用字符串函数。
b) 保持为字节数组(`ay`),使用`g_variant_get_fixed_array`或`g_variant_get_bytestring`来获取数据。
由于我们之前将特性定义为`ay`(字节数组),但读写操作中却使用了字符串函数,这会导致类型不匹配。为了简单起见,我们将特性类型改为字符串(`s`)。
修改步骤如下:
在XML定义中,将特性的`Value`属性类型从`ay`改为`s`:
```c
static const gchar char_interface_xml[] =
"<node>"
" <interface name='org.bluez.GattCharacteristic1'>"
" <property name='UUID' type='s' access='read'/>"
" <property name='Value' type='s' access='readwrite'/>" // 修改这里
" </interface>"
"</node>";
```
然后,在读写处理函数中,使用字符串类型:
读取函数保持不变(返回字符串):
```c
return g_variant_new_string("PimowResponse");
```
写入函数改为:
```c
const gchar *data = g_variant_get_string(value, &len);
```
这样,类型就一致了。
另外,在`handle_char_read`中,我们返回的字符串需要包含null终止符,但`g_variant_new_string`会自动处理,所以我们不需要指定长度。
让我们重新整理代码:
### 修正后的完整代码:
```c
#include <gio/gio.h>
#include <glib.h>
#include <stdlib.h>
#define ADAPTER_PATH "/org/bluez/hci0"
#define ADAPTER_INTERFACE "org.bluez.Adapter1"
#define SERVICE_PATH "/org/bluez/pimow_service"
#define CHAR_PATH "/org/bluez/pimow_service/char"
static GDBusConnection *connection = NULL;
static guint service_reg = 0;
static guint char_reg = 0;
// 处理蓝牙特性读取请求
static GVariant *handle_char_read(GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error,
gpointer user_data) {
g_print("Characteristic read request\n");
return g_variant_new_string("PimowResponse");
}
// 处理蓝牙特性写入请求
static gboolean handle_char_write(GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GVariant *value,
GError **error,
gpointer user_data) {
gsize len = 0;
const gchar *data = g_variant_get_string(value, &len);
g_print("Received data: %.*s (len=%d)\n", (int)len, data, (int)len);
return TRUE;
}
// D-Bus接口信息结构
static const GDBusInterfaceVTable char_interface_vtable = {
.get_property = handle_char_read,
.set_property = handle_char_write
};
// GATT特性接口XML定义
static const gchar char_interface_xml[] =
"<node>"
" <interface name='org.bluez.GattCharacteristic1'>"
" <property name='UUID' type='s' access='read'/>"
" <property name='Value' type='s' access='readwrite'/>"
" </interface>"
"</node>";
// GATT服务接口XML定义
static const gchar service_interface_xml[] =
"<node>"
" <interface name='org.bluez.GattService1'>"
" <property name='UUID' type='s' access='read'/>"
" </interface>"
"</node>";
// 注册蓝牙服务特性
static void register_char(void) {
GDBusNodeInfo *node_info = g_dbus_node_info_new_for_xml(char_interface_xml, NULL);
if (!node_info) {
g_printerr("Failed to parse characteristic XML\n");
return;
}
GDBusInterfaceInfo *iface_info = g_dbus_node_info_lookup_interface(node_info, "org.bluez.GattCharacteristic1");
// 注册特性对象
char_reg = g_dbus_connection_register_object(
connection,
CHAR_PATH,
iface_info,
&char_interface_vtable,
NULL, // user_data
NULL, // user_data_free_func
NULL); // GError
if (!char_reg) {
g_printerr("Failed to register characteristic\n");
}
// 设置特性UUID属性
g_dbus_connection_emit_signal(
connection,
NULL, // destination_bus_name
CHAR_PATH,
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
g_variant_new("(sa{sv}as)",
"org.bluez.GattCharacteristic1",
g_variant_new_array(
G_VARIANT_TYPE("{sv}"),
(GVariant *[]){
g_variant_new("{sv}", "UUID", g_variant_new_string("0000FFF1-0000-1000-8000-00805F9B34FB")),
},
1),
NULL),
NULL);
}
// 注册蓝牙服务
static void register_service(void) {
GDBusNodeInfo *node_info = g_dbus_node_info_new_for_xml(service_interface_xml, NULL);
if (!node_info) {
g_printerr("Failed to parse service XML\n");
return;
}
GDBusInterfaceInfo *iface_info = g_dbus_node_info_lookup_interface(node_info, "org.bluez.GattService1");
// 注册服务对象
service_reg = g_dbus_connection_register_object(
connection,
SERVICE_PATH,
iface_info,
NULL, // vtable - 服务不需要处理请求
NULL, // user_data
NULL, // user_data_free_func
NULL); // GError
if (!service_reg) {
g_printerr("Failed to register service\n");
return;
}
// 设置服务UUID属性
g_dbus_connection_emit_signal(
connection,
NULL, // destination_bus_name
SERVICE_PATH,
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
g_variant_new("(sa{sv}as)",
"org.bluez.GattService1",
g_variant_new_array(
G_VARIANT_TYPE("{sv}"),
(GVariant *[]){
g_variant_new("{sv}", "UUID", g_variant_new_string("0000FFF0-0000-1000-8000-00805F9B34FB")),
},
1),
NULL),
NULL);
// 注册特性
register_char();
}
// 设置蓝牙适配器属性
static void set_adapter_property(const char *prop, GVariant *value) {
GError *error = NULL;
g_dbus_connection_call_sync(connection,
"org.bluez",
ADAPTER_PATH,
"org.freedesktop.DBus.Properties",
"Set",
g_variant_new("(ssv)", ADAPTER_INTERFACE, prop, value),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error) {
g_printerr("Error setting %s: %s\n", prop, error->message);
g_error_free(error);
}
}
int main(void) {
GMainLoop *loop;
GError *error = NULL;
// 初始化主循环
loop = g_main_loop_new(NULL, FALSE);
// 连接到系统总线
connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
if (!connection) {
g_printerr("DBus connection failed: %s\n", error->message);
g_error_free(error);
return EXIT_FAILURE;
}
// 设置蓝牙适配器属性
set_adapter_property("Powered", g_variant_new_boolean(TRUE));
set_adapter_property("Discoverable", g_variant_new_boolean(TRUE));
set_adapter_property("Pairable", g_variant_new_boolean(TRUE));
set_adapter_property("Alias", g_variant_new_string("Pimow"));
g_print("Bluetooth adapter configured as 'Pimow'\n");
// 注册蓝牙服务
register_service();
// 向BlueZ注册应用
g_dbus_connection_call_sync(connection,
"org.bluez",
ADAPTER_PATH,
"org.bluez.GattManager1",
"RegisterApplication",
g_variant_new("(oa{sv})",
SERVICE_PATH,
g_variant_new_array(
G_VARIANT_TYPE("{sv}"),
NULL,
0
)
),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error) {
g_printerr("Failed to register application: %s\n", error->message);
g_error_free(error);
} else {
g_print("GATT application registered successfully\n");
}
g_print("Pimow Bluetooth is ready. Waiting for connections...\n");
g_main_loop_run(loop);
// 清理资源
if (service_reg) g_dbus_connection_unregister_object(connection, service_reg);
if (char_reg) g_dbus_connection_unregister_object(connection, char_reg);
g_main_loop_unref(loop);
g_object_unref(connection);
return EXIT_SUCCESS;
}
```
### 关键修正点:
1. **特性值类型变更**:
- 将特性的`Value`属性从`ay`(字节数组)改为`s`(字符串)。
- 这样可以使用`g_variant_new_string`和`g_variant_get_string`函数,避免类型错误。
2. **修正`g_variant_new_bytestring`调用**:
- 删除了多余的长度参数,只传递字符串指针。
3. **修正属性设置信号**:
- 使用数组形式传递属性字典,确保符合DBus的PropertiesChanged信号格式。
### 编译命令:
```bash
gcc -o pimow_bt pimow_bt.c `pkg-config --cflags --libs glib-2.0 gio-2.0`
```
### 运行测试:
程序运行后,使用蓝牙客户端(如手机APP或`gatttool`)连接设备名为"Pimow"的蓝牙设备,然后读写特性。
注意:如果仍然遇到问题,请检查BlueZ的版本,并确保DBus配置正确。
§§相关问题§§:
1. 如何为蓝牙服务添加多个特性(Characteristics)?
2. 如何处理蓝牙连接和断开事件?
3. 如何实现蓝牙低功耗(BLE)的广播数据?
4. 如何通过DBus监听蓝牙适配器的状态变化?
</think>
我理解编译错误的原因了。让我们修复 `g_variant_new_bytestring` 的使用问题。以下是完全修正后的代码:
```c
#include <gio/gio.h>
#include <glib.h>
#include <stdlib.h>
#define ADAPTER_PATH "/org/bluez/hci0"
#define ADAPTER_INTERFACE "org.bluez.Adapter1"
#define SERVICE_PATH "/org/bluez/pimow_service"
#define CHAR_PATH "/org/bluez/pimow_service/char"
static GDBusConnection *connection = NULL;
static guint service_reg = 0;
static guint char_reg = 0;
// 处理蓝牙特性读取请求
static GVariant *handle_char_read(GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error,
gpointer user_data) {
g_print("Characteristic read request\n");
// 使用正确的GVariant创建方式
return g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
"PimowResponse",
strlen("PimowResponse") + 1, // 包含null终止符
sizeof(guchar));
}
// 处理蓝牙特性写入请求
static gboolean handle_char_write(GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GVariant *value,
GError **error,
gpointer user_data) {
gsize len = 0;
const guchar *data = g_variant_get_fixed_array(value, &len, sizeof(guchar));
g_print("Received data: %.*s (len=%d)\n", (int)len, data, (int)len);
return TRUE;
}
// D-Bus接口信息结构
static const GDBusInterfaceVTable char_interface_vtable = {
.get_property = handle_char_read,
.set_property = handle_char_write
};
// GATT特性接口XML定义
static const gchar char_interface_xml[] =
"<node>"
" <interface name='org.bluez.GattCharacteristic1'>"
" <property name='UUID' type='s' access='read'/>"
" <property name='Value' type='ay' access='readwrite'/>"
" </interface>"
"</node>";
// GATT服务接口XML定义
static const gchar service_interface_xml[] =
"<node>"
" <interface name='org.bluez.GattService1'>"
" <property name='UUID' type='s' access='read'/>"
" </interface>"
"</node>";
// 注册蓝牙服务特性
static void register_char(void) {
GDBusNodeInfo *node_info = g_dbus_node_info_new_for_xml(char_interface_xml, NULL);
if (!node_info) {
g_printerr("Failed to parse characteristic XML\n");
return;
}
GDBusInterfaceInfo *iface_info = g_dbus_node_info_lookup_interface(node_info, "org.bluez.GattCharacteristic1");
// 注册特性对象
char_reg = g_dbus_connection_register_object(
connection,
CHAR_PATH,
iface_info,
&char_interface_vtable,
NULL, // user_data
NULL, // user_data_free_func
NULL); // GError
if (!char_reg) {
g_printerr("Failed to register characteristic\n");
}
// 设置特性UUID属性
g_dbus_connection_emit_signal(
connection,
NULL, // destination_bus_name
CHAR_PATH,
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
g_variant_new("(sa{sv}as)",
"org.bluez.GattCharacteristic1",
g_variant_new("(sa{sv}as)",
"UUID",
g_variant_new_string("0000FFF1-0000-1000-8000-00805F9B34FB"),
NULL),
NULL),
NULL);
}
// 注册蓝牙服务
static void register_service(void) {
GDBusNodeInfo *node_info = g_dbus_node_info_new_for_xml(service_interface_xml, NULL);
if (!node_info) {
g_printerr("Failed to parse service XML\n");
return;
}
GDBusInterfaceInfo *iface_info = g_dbus_node_info_lookup_interface(node_info, "org.bluez.GattService1");
// 注册服务对象
service_reg = g_dbus_connection_register_object(
connection,
SERVICE_PATH,
iface_info,
NULL, // vtable - 服务不需要处理请求
NULL, // user_data
NULL, // user_data_free_func
NULL); // GError
if (!service_reg) {
g_printerr("Failed to register service\n");
return;
}
// 设置服务UUID属性
g_dbus_connection_emit_signal(
connection,
NULL, // destination_bus_name
SERVICE_PATH,
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
g_variant_new("(sa{sv}as)",
"org.bluez.GattService1",
g_variant_new("(sa{sv}as)",
"UUID",
g_variant_new_string("0000FFF0-0000-1000-8000-00805F9B34FB"),
NULL),
NULL),
NULL);
// 注册特性
register_char();
}
// 设置蓝牙适配器属性
static void set_adapter_property(const char *prop, GVariant *value) {
GError *error = NULL;
g_dbus_connection_call_sync(connection,
"org.bluez",
ADAPTER_PATH,
"org.freedesktop.DBus.Properties",
"Set",
g_variant_new("(ssv)", ADAPTER_INTERFACE, prop, value),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error) {
g_printerr("Error setting %s: %s\n", prop, error->message);
g_error_free(error);
}
}
int main(void) {
GMainLoop *loop;
GError *error = NULL;
// 初始化主循环
loop = g_main_loop_new(NULL, FALSE);
// 连接到系统总线
connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
if (!connection) {
g_printerr("DBus connection failed: %s\n", error->message);
g_error_free(error);
return EXIT_FAILURE;
}
// 设置蓝牙适配器属性
set_adapter_property("Powered", g_variant_new_boolean(TRUE));
set_adapter_property("Discoverable", g_variant_new_boolean(TRUE));
set_adapter_property("Pairable", g_variant_new_boolean(TRUE));
set_adapter_property("Alias", g_variant_new_string("Pimow"));
g_print("Bluetooth adapter configured as 'Pimow'\n");
// 注册蓝牙服务
register_service();
// 向BlueZ注册应用
g_dbus_connection_call_sync(connection,
"org.bluez",
ADAPTER_PATH,
"org.bluez.GattManager1",
"RegisterApplication",
g_variant_new("(oa{sv})",
SERVICE_PATH,
g_variant_new_array(
G_VARIANT_TYPE("{sv}"),
NULL,
0
)
),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error) {
g_printerr("Failed to register application: %s\n", error->message);
g_error_free(error);
} else {
g_print("GATT application registered successfully\n");
}
g_print("Pimow Bluetooth is ready. Waiting for connections...\n");
g_main_loop_run(loop);
// 清理资源
if (service_reg) g_dbus_connection_unregister_object(connection, service_reg);
if (char_reg) g_dbus_connection_unregister_object(connection, char_reg);
g_main_loop_unref(loop);
g_object_unref(connection);
return EXIT_SUCCESS;
}
```
### 关键修正点:
1. **修复 `g_variant_new_bytestring` 问题**:
```c
// 错误用法
return g_variant_new_bytestring("PimowResponse", 13);
// 正确用法(使用固定字节数组)
return g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
"PimowResponse",
strlen("PimowResponse") + 1,
sizeof(guchar));
```
2. **统一字节数组处理**:
- 读取时使用 `g_variant_new_fixed_array` 创建字节数组
- 写入时使用 `g_variant_get_fixed_array` 获取字节数组数据
```c
const guchar *data = g_variant_get_fixed_array(value, &len, sizeof(guchar));
```
3. **保持特性类型一致性**:
特性类型保持为 `ay` (字节数组),以符合蓝牙规范:
```xml
<property name='Value' type='ay' access='readwrite'/>
```
### 编译和运行步骤:
1. 复制上面的代码到嵌入式设备上的 `pimow_bt.c` 文件
2. 安装依赖:
```bash
sudo apt update
sudo apt install -y libglib2.0-dev libdbus-1-dev bluez bluez-tools
```
3. 编译程序:
```bash
gcc -o pimow_bt pimow_bt.c `pkg-config --cflags --libs glib-2.0 gio-2.0`
```
4. 运行程序(需要root权限):
```bash
sudo ./pimow_bt
```
### 验证程序是否工作:
1. 检查蓝牙适配器状态:
```bash
hciconfig
```
应看到类似输出:
```
hci0: Type: Primary Bus: USB
BD Address: 00:11:22:33:44:55 ACL MTU: 1021:8 SCO MTU: 64:1
Name: 'Pimow'
Discovering: On
```
2. 使用手机或另一设备搜索蓝牙设备,应该能看到名为 "Pimow" 的设备。
3. 使用 `bluetoothctl` 验证:
```bash
sudo bluetoothctl
```
在交互界面中输入:
```
scan on
devices
```
应看到类似:
```
Device 00:11:22:33:44:55 Pimow
```
### 如果仍然遇到问题:
1. **检查GLib版本**:
```bash
pkg-config --modversion glib-2.0
```
如果版本低于2.50,部分API可能不可用
2. **使用调试模式**:
```bash
G_MESSAGES_DEBUG=all sudo ./pimow_bt
```
3. **检查DBus权限**:
确保程序有权限访问BlueZ服务:
```bash
sudo nano /etc/dbus-1/system.d/pimow.conf
```
添加以下内容:
```xml
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="org.bluez"/>
<allow send_destination="org.bluez"/>
</policy>
</busconfig>
```
重启DBus:
```bash
sudo systemctl restart dbus
```
阅读全文
相关推荐



















