编译
目录结构如下:
.
├── app
├── build.sh
├── dbus-1.16.2
├── dbus-1.16.2.tar.xz
├── dbus-cxx-2.5.2
├── dbus-cxx-2.5.2.tar.gz
├── dbus-glib-0.114
├── dbus-glib-0.114.tar.gz
├── expat-2.7.1
├── expat-2.7.1.tar.bz2
├── linux.txt
└── output
加粗的为必要文件
下载dbus源码
dbus源码
下载expat源码
expat源码
安装meson工具
sudo apt install meson
编写配置文件 Linux.txt
[binaries]
c = 'aarch64-mix210-linux-gcc'
cpp = 'aarch64-mix210-linux-g++'
ar = 'aarch64-mix210-linux-ar'
strip = 'aarch64-mix210-linux-strip'
#pkgconfig = '/usr/bin/x86_64-pc-linux-gnu-pkg-config'
#cmake = ''
ld = 'aarch64-mix210-linux-ld'
#pcap-config = ''
[built-in options]
c_args = ['-O2', '-pipe', '-feliminate-unused-debug-types']
c_link_args = ['-Wl,-O1', '-Wl,--hash-style=gnu', '-Wl,--as-needed']
cpp_args = ['-O2', '-pipe', '-feliminate-unused-debug-types']
cpp_link_args = ['-Wl,-O1', '-Wl,--hash-style=gnu', '-Wl,--as-needed']
编写编译脚本
#/bin/sh
ARCH=arm64
CROSS=aarch64-mix210-linux
DIR=`pwd`
OUTPUT=$DIR/output
CHIP=
# export CROSS_COMPILE=$CROSS-
EXPAT=expat-2.7.1
DBUS=dbus-1.16.2
DBUS_GLIB=dbus-glib-0.114
if [ ! -d $OUTPUT ]
then
mkdir -p $OUTPUT
fi
case $1 in
ss528v100)
CHIP=$1
rm $OUTPUT -rf
pushd $EXPAT
./configure \
--prefix=$OUTPUT/$EXPAT \
--host=$CROSS \
CC=$CROSS-gcc \
|| exit 1
make -j12 || exit 1
make install || exit 1
$CROSS-strip $OUTPUT/$EXPAT/bin/*
$CROSS-strip $OUTPUT/$EXPAT/lib/*
popd
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$OUTPUT/$EXPAT/lib/pkgconfig
# #rm -rf $DBUS
# #tar -xf $DBUS.tar.xz
pushd $DBUS
# 老版本用这个编译
# make clean
# make distclean
# ./autogen.sh
# ./configure \
# --prefix=$OUTPUT/$DBUS \
# --host=$CROSS \
# CC=$CROSS-gcc \
# CXX=$CROSS-g++ \
# --without-x \
# --disable-tests \
# || exit 1
# make -j12 || exit 1
# make install || exit 1
#新版本改用了meson编译
meson setup --cross-file $DIR/linux.txt -D systemd=disabled --buildtype=release $OUTPUT/build
pushd $OUTPUT/build
ninja || exit 1
DESTDIR=$OUTPUT/$DBUS ninja install || exit 1
chown -v root:messagebus $OUTPUT/$DBUS/usr/libexec/dbus-daemon-launch-helper
chmod -v 4750 $OUTPUT/$DBUS/usr/libexec/dbus-daemon-launch-helper
$CROSS-strip $OUTPUT/$DBUS/usr/local/bin/*
$CROSS-strip $OUTPUT/$DBUS/usr/local/libexec/*
$CROSS-strip $OUTPUT/$DBUS/usr/local/lib/*
# meson compile
# meson install
popd
popd
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$OUTPUT/$DBUS/usr/local/lib/pkgconfig
sudo cp $OUTPUT/$DBUS/usr/local/lib/* /opt/linux/x86-arm/aarch64-mix210-linux/aarch64-linux-gnu/lib/ -R
sudo cp $OUTPUT/$DBUS/usr/local/include/dbus-1.0/dbus /opt/linux/x86-arm/aarch64-mix210-linux/aarch64-linux-gnu/include/ -R
sudo cp $OUTPUT/$DBUS/usr/local/lib/dbus-1.0/include/dbus/dbus-arch-deps.h /opt/linux/x86-arm/aarch64-mix210-linux/aarch64-linux-gnu/include/dbus/
rm -rf $OUTPUT/$DBUS/usr/local/lib/cmake
rm -rf $OUTPUT/$DBUS/usr/local/lib/dbus-1.0
rm -rf $OUTPUT/$DBUS/usr/local/lib/dbus-1.0/include
rm -rf $OUTPUT/$DBUS/usr/local/lib/dbus-1.0/include/dbus
rm -rf $OUTPUT/$DBUS/usr/local/lib/pkgconfig
rm -rf $OUTPUT/$DBUS/usr/local/include
cp $OUTPUT/* $OUTPUT/$DBUS/* ../image/rootfs/ -R || exit 1
;;
clean)
rm $OUTPUT -rf
exit 0
;;
*)
echo "param error!" ; exit 1;
esac
使用
运行deaemon
eval `dbus-launch --auto-syntax`
- 如果想要新打开的ssh链接和串口共用一个dbus地址环境变量则可以使用下面的方法实现
- 在启动脚本中加入下面的命令
eval `dbus-launch`
echo "export DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" >> /root/.profile
echo "export DBUS_SESSION_BUS_PID=$DBUS_SESSION_BUS_PID" >> /root/.profile
QT远程部署时需要添加环境变量,将下图中设备里实际的环境变量填到QtCreator中
DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/dbus-rx5jGEQamM,guid=b68253f930c5ffa9023c181601c5c897
即可实现远程运行程序,注意每次dbus-daemon的启动这个环境变量都需要手动更新
测试QT DBUS与C程序DBUS
使用QT自带的QDBUS demo,直接运行即可
QT测试例程
QT源码
├── main.cpp
├── org.example.signal.xml
├── signal_demo.pro
└── signal_demo.pro.user
- main.cpp
#include <QtDBus>
#include <QPushButton>
#include <QApplication>
#include "signal_interface.h"
#include "signal_adaptor.h"
// 发送端组件
class Sender : public QWidget {
Q_OBJECT
public:
Sender() {
auto *btn = new QPushButton("send signal", this);
connect(btn, &QPushButton::clicked, [this] {
QDBusMessage msg = QDBusMessage::createSignal("/", "org.example.SignalDemo", "DemoSignal");
msg << "msg" << 42;
QDBusConnection::sessionBus().send(msg);
});
}
};
// 接收端组件
class Receiver : public QObject {
Q_OBJECT
public slots:
void HandleSignal(QString msg, int val) {
qDebug() << "recieve:" << msg << "value:" << val;
}
};
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// 初始化D-Bus接口
OrgExampleSignalDemoInterface iface("org.example.SignalDemo", "/",
QDBusConnection::sessionBus());
// 发送端界面
Sender sender;
sender.show();
// 接收端注册
Receiver receiver;
QDBusConnection::sessionBus().registerObject("/receiver", &receiver);
QDBusConnection::sessionBus().connect("", "/", "org.example.SignalDemo", "DemoSignal",
&receiver, SLOT(HandleSignal(QString,int)));
return a.exec();
}
#include "main.moc"
- org.example.signal.xml
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.example.SignalDemo">
<signal name="DemoSignal">
<arg name="message" type="s" direction="out"/>
<arg name="value" type="i" direction="out"/>
</signal>
</interface>
</node>
- signal_demo.pro
# 包含 QtDBus 模块
QT += dbus gui core widgets
# 项目名称
TARGET = signal_demo
# 模板类型,应用程序
TEMPLATE = app
# 源文件
SOURCES += main.cpp
# 处理 D-Bus XML 文件
DBUS_ADAPTORS += org.example.signal.xml
DBUS_INTERFACES += org.example.signal.xml
target.path = /root
INSTALLS += target
c例程
.
├── Makefile
├── receiver.c
└── sender.c
- Makefile
# DBus 信号发送端编译配置
CC = aarch64-mix210-linux-gcc
CFLAGS = -Wall -Wextra # 自动获取DBus头文件路径
LDFLAGS = -ldbus-1 # 自动获取DBus库链接参数
# 编译目标:生成sender可执行文件
all: sender receiver
sender: sender.c
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
receiver: receiver.c
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
# 清理生成文件
clean:
rm -f sender receiver
- receiver.c
#include <dbus/dbus.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
DBusError error;
DBusConnection *conn;
dbus_error_init(&error);
// 连接到会话总线
conn = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "连接总线失败: %s\n", error.message);
dbus_error_free(&error);
return 1;
}
if (conn == NULL){
printf("conn null");
return 1;
}
// 注册匹配规则(监听指定接口和信号)
char *rule = "type='signal',interface='org.example.SignalDemo'";
dbus_bus_add_match(conn, rule, &error);
dbus_connection_flush(conn);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "Match Error (%s)\n", error.message);
exit(1);
}
// 进入主循环等待信号
while (1) {
dbus_connection_read_write(conn, 0);
DBusMessage *msg = dbus_connection_pop_message(conn);
if (msg == NULL) {
printf("%s\n","wait msg");
sleep(1); // 无消息时休眠
continue;
}
DBusMessageIter args;
const char *str;
int num;
// 检查是否是目标信号
if (dbus_message_is_signal(msg, "org.example.SignalDemo", "DemoSignal")) {
// 解析参数
if (!dbus_message_iter_init(msg, &args)) {
fprintf(stderr, "信号无参数\n");
continue;
}
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
fprintf(stderr, "第一个参数类型错误\n");
continue;
}
dbus_message_iter_get_basic(&args, &str);
dbus_message_iter_next(&args);
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_INT32) {
fprintf(stderr, "第二个参数类型错误\n");
continue;
}
dbus_message_iter_get_basic(&args, &num);
printf("接收到信号!参数:%s, %d\n", str, num);
}
else {
// 打印 msg 的内容
char *msg_str = dbus_message_get_path(msg);
if (msg_str != NULL) {
printf("接收到非目标信号,消息内容:%s\n", msg_str);
} else {
printf("无法将消息转换为字符串\n");
}
}
dbus_message_unref(msg); // 消息已由回调处理
}
dbus_connection_unref(conn);
return 0;
}
- sender.c
#include <dbus/dbus.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
DBusError error;
DBusConnection *conn;
DBusMessage *msg;
DBusMessageIter args;
dbus_uint32_t serial = 0;
int ret;
// 初始化错误结构体
dbus_error_init(&error);
// 连接到会话总线(也可改为系统总线:dbus_bus_get(DBUS_BUS_SYSTEM, &error))
conn = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "连接总线失败: %s\n", error.message);
dbus_error_free(&error);
return 1;
}
if (conn == NULL) return 1;
// 创建信号消息(接口: org.example.SignalDemo,路径: /org/example/SignalDemo,信号名: DemoSignal)
msg = dbus_message_new_signal("/",
"org.example.SignalDemo",
"DemoSignal");
if (msg == NULL) {
fprintf(stderr, "创建信号消息失败\n");
return 1;
}
// 向信号中添加参数(示例:发送一个字符串和一个整数)
dbus_message_iter_init_append(msg, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(const char*){"Hello DBus"})) {
fprintf(stderr, "添加字符串参数失败\n");
dbus_message_unref(msg);
return 1;
}
int num = 123;
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &num)) {
fprintf(stderr, "添加整数参数失败\n");
dbus_message_unref(msg);
return 1;
}
// 发送信号
if (!dbus_connection_send(conn, msg, &serial)) {
fprintf(stderr, "发送信号失败\n");
dbus_message_unref(msg);
return 1;
}
dbus_connection_flush(conn); // 立即发送
// 释放资源
dbus_message_unref(msg);
dbus_connection_unref(conn);
return 0;
}
测试效果如下
执行receiver &
执行QT程序
qt界面上点击发送或执行./sender
即可看到测试结果