gpt4 book ai didi

C++ 设计多层通信的软件架构

转载 作者:行者123 更新时间:2023-11-28 04:23:48 25 4
gpt4 key购买 nike

众所周知,每个通信 channel 都有不同的最大数据长度能力。例如最大。 USB HID 中的数据长度为 64 字节,或者对于 UART modbus channel 为 256 字节。但是作为用户,我不想关心这些限制。我的通信应该能够将大数据包拆分为多个较小的数据包(取决于 channel 的最大数据长度)。实际的拆分流程是一样的,只是每个包的数据长度不同。

这就是我编写通用通信 API 的动机。

那么让我们从更高的层次开始:

template<size_t user_data_length>
class CSlave_Com_API: protected CSlave_Com_Mid_level<user_data_length>
{
/*
* all of these Functions need elements from CSlave_Com_Mid_level to
* work correctly
*/
public:

/**
* This Function is called by the user thread. It need access to some elements from CSlave_Com_Mid_level.
* These elements are not shown here to make this problem better understandable
*
* Processes a Received Request and generates the answer. The answer is copied to pRequest as well
* @param pRequest Pointer to the Request
* @return true wenn an answer was generated
*/
bool Process_Request(CRequest* const pRequest);

private:

/**
* This Function is called within Process_Request (by the user thread).
* It need access to some elements from CSlave_Com_Mid_level.
* These elements are not shown here to make this problem better understandable
*
* Tells the LL Driver that the answer has been prepared (and stored to pRequest).
* The answer is no ready to be sent
* @param pRequest Pointer to the request
* @return true if the LL Driver has been notified correctly
*/
bool Send_Answer(CRequest* const pRequest);

/**
* This Function is called within Process_Request (by the user thread).
* It need access to some elements from CSlave_Com_Mid_level.
* These elements are not shown here to make this problem better understandable
*
* Tells the LL driver to abort the request because something went wrong
* @param pRequest Pointer to the Request
* @return true if the LL driver has been notified correctly
*/
bool Abort_Request(CRequest* const pRequest);
};

template<size_t user_data_length>
class CSlave_Com_Mid_level
{

public:
///This is the structure of a single packet with is sent or received
struct Single_Packet_T
{
//some header Info...
uint8_t data[user_data_length]; ///< the actual user data
};

/**
* This Function is called by the driver thread. It need access to some elements from CSlave_Com_Mid_level.
* These elements are not shown here to make this problem better understandable
*
* Called be the LL Driver when new data was received
* @param rx_packet Received data
* @return true when the received data could be processed
*/
bool Process_received_Packet(const Single_Packet_T& rx_packet);

/**
* This Function is called by the driver thread. It need access to some elements from CSlave_Com_Mid_level.
* These elements are not shown here to make this problem better understandable
*
* Called by the LL driver. Stores new data to sent in tx_packet
* @param tx_packet Storage buffer for the new TX Data
* @return true when the buffer was filled correctly
*/
bool Get_Next_Packet_To_Send(Single_Packet_T& tx_packet);

private:
/// This queue contains all currently processed requests
QueueHandle_t requests;
};

想法是您可以为每个 channel 初始化一个 API 实例。即

CSlave_Com_API<64> usb_slave_com;
CSlave_Com_API<256> modbus_slave_com;

现在 LL 显然对于每个 channel 都非常不同。问题是,我有两个不同的任务:高级任务由用户请求触发,实际硬件通信在自己单独的任务中运行,以确保仅在硬件实际准备好发送数据时才发送数据。

示例 LL 类可能如下所示:

class CSlave_Com_LL_Slave_Com
{
public:
/**
*Constructor
* @param mid_level_reference reference to the used midlevel class instance. This instance is needed to correctly
* pass the received data to the higher levels and to get the next data to be send
*/
CSlave_Com_LL_Slave_Com(const CSlave_Com_Mid_level<message_length>& mid_level_reference);

///Destruktor
~CSlave_Com_LL_Slave_Com();

private:
///Midlevel Reference
const CSlave_Com_Mid_level<message_length>& mid_level_instance;
};

问题是:我的 LL 类需要访问某些 API 实例的中级基础。然而,这个基地受到保护。显然我可以公开中层基础,但这意味着用户可以(意外地)访问中层。我不想这样。

您对如何解决我的问题有什么建议吗?

谢谢你的帮助:)

最佳答案

更新:抱歉,我想念你,这是解决方案,我想你要求的是:

#include <string>
#include <iostream>


template<size_t user_data_length>
class CSlave_Com_Mid_level
{

public:
///This is the structure of a single packet with is sent or received
struct Single_Packet_T
{
//some header Info...
uint8_t data[user_data_length]; ///< the actual user data
};

/**
* Called be the LL Driver when new data was received
* @param rx_packet Received data
* @return true when the received data could be processed
*/
bool Process_received_Packet(const Single_Packet_T& rx_packet) const {
std::cout << "Test\n";
return false;
}

/**
* Called by the LL driver. Stores new data to sent in tx_packet
* @param tx_packet Storage buffer for the new TX Data
* @return true when the buffer was filled correctly
*/
bool Get_Next_Packet_To_Send(Single_Packet_T& tx_packet);


};

template<size_t user_data_length>
class CSlave_Com_API;

template <size_t message_length>
class CSlave_Com_LL_Slave_Com
{
public:
/**
*Constructor
* @param mid_level_reference reference to the used midlevel class instance. This instance is needed to correctly
* pass the received data to the higher levels and to get the next data to be send
*/
CSlave_Com_LL_Slave_Com(const CSlave_Com_API<message_length>& mid_level_reference)
: mid_level_instance(mid_level_reference) {
typename CSlave_Com_Mid_level<message_length>::Single_Packet_T packet{};
this->mid_level_instance.Process_received_Packet(packet);
}

///Destruktor
~CSlave_Com_LL_Slave_Com() = default;

private:
///Midlevel Reference
const CSlave_Com_Mid_level<message_length>& mid_level_instance;
};

template<size_t user_data_length>
class CSlave_Com_API: protected CSlave_Com_Mid_level<user_data_length> {
friend class CSlave_Com_LL_Slave_Com<user_data_length>;
};

int main()
{
CSlave_Com_API<42UL> foo{};
CSlave_Com_LL_Slave_Com<42UL> bar{foo};
}

关于C++ 设计多层通信的软件架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54905069/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com