【嵌入式linux Dbus aarch64交叉编译】基于海思编译dbus并移植使用,QT测试QDBUS

编译

目录结构如下:
.
├── 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中
QtCreator配置ENV信息

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即可看到测试结果
测试结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值