您现在的位置是:网站首页> C/C++
Linux C编程笔记
- C/C++
- 2024-09-24
- 134人已阅读
Linux C编程笔记
在 linux下C C++的头文件和库文件所在目录
在Linux系统下,C/C++ 的头文件和库文件通常位于以下几个目录:
头文件:
/usr/include: 这是系统默认的 C/C++ 头文件目录,包含了 C/C++ 标准库以及其他常用库的头文件,例如 stdio.h, iostream, algorithm 等。
/usr/local/include: 这个目录用于存放用户本地安装的软件包的头文件,以便与系统自带的头文件区分开来。
/usr/include/<软件包名称>: 一些软件包会将自己的头文件安装到 /usr/include 目录下的子目录中,例如 /usr/include/python3.8 存放 Python 3.8 的头文件。
/opt/<软件包名称>/include: 一些大型软件包会将自己的头文件安装到 /opt 目录下的子目录中。
库文件:
/usr/lib: 这是系统默认的库文件目录,包含了 C/C++ 标准库以及其他常用库的动态链接库和静态链接库,例如 libc.so, libstdc++.a 等。
/usr/local/lib: 这个目录用于存放用户本地安装的软件包的库文件,以便与系统自带的库文件区分开来。
/usr/lib/<架构>: 一些库文件会根据不同的 CPU 架构存放在不同的目录下,例如 /usr/lib/x86_64-linux-gnu 存放 x86_64 架构的库文件。
/usr/lib/<软件包名称>: 一些软件包会将自己的库文件安装到 /usr/lib 目录下的子目录中。
/opt/<软件包名称>/lib: 一些大型软件包会将自己的库文件安装到 /opt 目录下的子目录中。
需要注意的是:
以上只是一些常见的目录,具体的目录结构可能因 Linux 发行版和软件包的安装方式而有所不同。
可以使用 locate 命令查找特定头文件或库文件的路径,例如 locate stdio.h 或 locate libstdc++.so。
在编译 C/C++ 程序时,可以使用 -I 参数指定头文件目录,使用 -L 参数指定库文件目录,使用 -l 参数指定链接的库文件
linux下用C操作常规蓝牙和低功耗蓝牙
常规蓝牙确保你的系统已经安装了BlueZ库和开发包:
sudo apt-get install libbluetooth-dev
然后,这里是一个基本的C程序示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/l2cap.h>
#define BLE_ATT_CID 4
int main() {
int device_id = hci_get_route(NULL);
int device_handle = 0;
int sock = 0;
struct sockaddr_l2 addr = { 0 };
char dest[18] = "XX:XX:XX:XX:XX:XX"; // 替换为你的BLE设备地址
// 打开蓝牙设备
device_handle = hci_open_dev(device_id);
if (device_handle < 0) {
perror("Failed to open device");
exit(1);
}
// 创建L2CAP socket
sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
if (sock < 0) {
perror("Failed to create L2CAP socket");
exit(1);
}
// 设置目标地址
addr.l2_family = AF_BLUETOOTH;
addr.l2_cid = htobs(BLE_ATT_CID);
str2ba(dest, &addr.l2_bdaddr);
// 连接到BLE设备
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("Failed to connect");
close(sock);
exit(1);
}
printf("Connected to %s\n", dest);
// 发送数据
char message[] = "Hello, BLE!";
if (write(sock, message, sizeof(message)) < 0) {
perror("Failed to send data");
} else {
printf("Sent: %s\n", message);
}
// 接收数据
char buffer[1024] = { 0 };
int bytes_read = read(sock, buffer, sizeof(buffer));
if (bytes_read > 0) {
printf("Received: %s\n", buffer);
} else if (bytes_read < 0) {
perror("Failed to receive data");
}
// 关闭连接
close(sock);
return 0;
}
编译和运行这个程序:
gcc -o ble_example ble_example.c -lbluetooth
sudo ./ble_example
注意事项:
你需要将 XX:XX:XX:XX:XX:XX 替换为实际的BLE设备地址。
这个例子使用的是L2CAP协议,这是BLE通信的底层协议。在实际应用中,你可能需要实现更高层的GATT协议。
这个程序需要root权限运行,因为它直接访问蓝牙硬件。
这只是一个基本的例子。实际的BLE通信可能涉及服务发现、特征读写等更复杂的操作。
错误处理在这个例子中很简单,在实际应用中你可能需要更健壮的错误处理机制。
这个例子假设BLE设备已经配对和连接。在实际应用中,你可能需要先进行设备扫描和配对过程。
要深入了解BLE编程,建议查阅BlueZ的官方文档和更多的示例代码。同时,考虑使用一些更高级的库,如 gattlib,它提供了更方便的 API 来处理 BLE 通信。
低功耗蓝牙确保安装了必要的开发库:
sudo apt-get install libglib2.0-dev libgio2.0-cil-dev
然后,这里是一个基本的C程序示例,展示如何扫描BLE设备、连接设备、并读取特征值:
#include <stdio.h>
#include <glib.h>
#include <gio/gio.h>
#define BLUEZ_BUS_NAME "org.bluez"
#define BLUEZ_INTERFACE_ADAPTER1 "org.bluez.Adapter1"
#define BLUEZ_INTERFACE_DEVICE1 "org.bluez.Device1"
#define BLUEZ_INTERFACE_GATTCHAR1 "org.bluez.GattCharacteristic1"
static GMainLoop *main_loop = NULL;
static void on_characteristic_read(GObject *source_object, GAsyncResult *res, gpointer user_data) {
GVariant *value;
GError *error = NULL;
value = g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, &error);
if (error != NULL) {
g_print("Error reading characteristic: %s\n", error->message);
g_error_free(error);
return;
}
GVariant *array;
g_variant_get(value, "(ay)", &array);
gsize n;
const guchar *data = g_variant_get_fixed_array(array, &n, sizeof(guchar));
g_print("Characteristic value: ");
for (gsize i = 0; i < n; i++) {
g_print("%02x ", data[i]);
}
g_print("\n");
g_variant_unref(value);
g_main_loop_quit(main_loop);
}
static void on_device_connected(GObject *source_object, GAsyncResult *res, gpointer user_data) {
GError *error = NULL;
GVariant *result;
result = g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, &error);
if (error != NULL) {
g_print("Error connecting to device: %s\n", error->message);
g_error_free(error);
return;
}
g_print("Connected to device\n");
// 这里应该实现服务和特征发现
// 为了简化,我们假设已知特征的路径
const gchar *char_path = "/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service000a/char000b";
GDBusProxy *char_proxy = g_dbus_proxy_new_for_bus_sync(
G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
BLUEZ_BUS_NAME,
char_path,
BLUEZ_INTERFACE_GATTCHAR1,
NULL,
&error
);
if (error != NULL) {
g_print("Error creating characteristic proxy: %s\n", error->message);
g_error_free(error);
return;
}
g_dbus_proxy_call(
char_proxy,
"ReadValue",
g_variant_new("(a{sv})", NULL),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
on_characteristic_read,
NULL
);
g_object_unref(char_proxy);
g_variant_unref(result);
}
static void on_device_found(GDBusProxy *proxy, GVariant *changed_properties, GStrv invalidated_properties, gpointer user_data) {
GVariantIter *iter;
const gchar *key;
GVariant *value;
g_variant_get(changed_properties, "a{sv}", &iter);
while (g_variant_iter_loop(iter, "{&sv}", &key, &value)) {
if (g_strcmp0(key, "Address") == 0) {
const gchar *address = g_variant_get_string(value, NULL);
g_print("Found device: %s\n", address);
// 连接到设备
g_dbus_proxy_call(
proxy,
"Connect",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
on_device_connected,
NULL
);
break;
}
}
g_variant_iter_free(iter);
}
int main(void) {
GError *error = NULL;
GDBusProxy *adapter_proxy;
main_loop = g_main_loop_new(NULL, FALSE);
adapter_proxy = g_dbus_proxy_new_for_bus_sync(
G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
BLUEZ_BUS_NAME,
"/org/bluez/hci0",
BLUEZ_INTERFACE_ADAPTER1,
NULL,
&error
);
if (error != NULL) {
g_print("Error creating adapter proxy: %s\n", error->message);
g_error_free(error);
return 1;
}
g_signal_connect(adapter_proxy, "g-properties-changed", G_CALLBACK(on_device_found), NULL);
// 开始扫描
g_dbus_proxy_call_sync(
adapter_proxy,
"StartDiscovery",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error
);
if (error != NULL) {
g_print("Error starting discovery: %s\n", error->message);
g_error_free(error);
return 1;
}
g_main_loop_run(main_loop);
g_object_unref(adapter_proxy);
g_main_loop_unref(main_loop);
return 0;
}
编译和运行这个程序:
gcc -o ble_example ble_example.c `pkg-config --cflags --libs glib-2.0 gio-2.0` -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include
sudo ./ble_example
注意事项:
这个例子展示了如何扫描BLE设备、连接到设备、并读取一个特征值。你需要替换 XX_XX_XX_XX_XX_XX 为实际的设备地址,并修改特征路径以匹配你的设备。
这个程序需要root权限运行,因为它需要访问系统的D-Bus。
这只是一个基本的例子。实际的BLE应用可能需要更复杂的服务和特征发现过程。
错误处理在这个例子中很简单,在实际应用中你可能需要更健壮的错误处理机制。
这个例子使用了同步和异步的D-Bus调用。在实际应用中,你可能需要更多地使用异步调用以提高性能。
为了简化,这个例子没有实现写入特征或订阅通知的功能。这些功能可以用类似的方式实现。
要深入了解Linux下的BLE编程,建议查阅BlueZ的官方文档和D-Bus规范。同时,考虑使用一些更高级的库,如 bluez-dbus,它提供了更方便的API来处理BLE通信。
上一篇:VC相关信息