【问题标题】:How can two C++ libraries share a static buffer?两个 C++ 库如何共享一个静态缓冲区?
【发布时间】:2017-05-23 13:10:01
【问题描述】:

简介

我正在开发我的第一个嵌入式应用程序(在 Arduino 上),它从许多现成的组件中获取输入并控制它们。这是一个完全私人的非商业项目。 (只是为了我自己的利益而做一些有趣的/训练练习。)

Arduino 库只是 C++ 源代码的压缩集合,其中包含一个 C++ 和 .h 文件,用于呈现库的接口。就这个问题而言,只需将每个库视为我从其他人那里获得的资源集合。

可以使用免费提供的库(具有良好声誉)来控制两个更复杂的组件,我希望使用这些库来避免重新发明轮子。但是,这两个库都声明了许多数组,这些数组占用了非常有限的可用数据空间。

在启动时,我的应用程序将测试一个开关,该开关将确定在下一次电源循环之前将使用两个组件中的哪一个。我永远不会同时使用这两个组件。

我的问题是什么?

我想更改库以共享 RAM 中的相同空间,但我发现我对 C++ 的了解太有限了。

现有代码是什么样的?

库 A 声明一个缓冲区如下:

class A
{
 public:
    char name[50];
    char address[100];
}

库 B 声明一个缓冲区如下:

class B
{
 public: 
    static char name[];
    static char address[];
}

并且B的调用者需要定义缓冲区如下:

    char B::name[50];
    char B::address[100];

可能的选择

我可以轻松地对库 A 进行少量更改,以传递指向由我的应用程序定义的缓冲区的指针。但是,库 B 比较棘手,因为缓冲区被声明为静态并由许多静态方法使用。

我可以更改库 B 以将所有使用这些缓冲区的静态方法转换为非静态方法。但这将是一项重要的工作,并且会偏离我想要的更多内容。如果有一天我想,这样的更改会使我更难更新我的应用程序以使用原作者的更高版本的库。

我假设我可以将 B:name[] 和 B::address[] 的地址传递给库 A,但是将 B 类的缓冲区传递给 A 类感觉就像一个粗略的障碍。

考虑到硬件环境,我不介意定义一个足够大的缓冲区来存储名称和地址,然后在库中对缓冲区使用偏移量。但我的主要问题阻止我在图书馆 B 中这样做。

问题

总而言之,我的问题是我不能让两个库共享一个完全在两个类之外定义的缓冲区,而不更改库 B 以便它不使用静态方法。

任何人都可以提出任何语言技巧来巧妙地解决我的问题,只需进行少量代码更改或可以自动或使用宏进行的更改吗?

【问题讨论】:

  • 您可以使用指针或对缓冲区的引用。然后他们共享同一个空间。
  • “诀窍”是使用指针和 new/delete[] 作为 B 的调用者
  • @Ðаn 我会考虑使用constexpr std::string_view,将其全部移动到只读段中可以很容易地共享内存。唯一需要注意的是整个事情必须是constexpr
  • @Ðаn : Arduino 是一种小型嵌入式设备。 string 的开销可能大得不合理。

标签: c++ arrays static


【解决方案1】:

不太确定你觉得可以接受的变化程度。

但是如何只更改 class B 的标头和应用程序,而保留其实现的其余部分?

class B
{
 public: 
    static char* name;
    static char* address;
}

B 的调用者定义缓冲区如下:

char name[50];
char address[100];
char* B::name = name;
char* B::address = address;

然后您也可以按照您的计划将nameaddress 传递给class A

所以问题是:为什么这适用于 B 中的其他代码?

首先,它需要使用相同的头文件进行编译。 除此之外,鉴于它实际上无法直接看到数组的大小,因此它或多或少可以正常工作而无需进一步更改。

可能的问题在于它是否包含需要数组参数而不是指针的方法或函数。数组衰减为指针,但不是相反。 如果是这种情况,您还必须将参数更改为这些函数。

但是,鉴于首先存在单例模式和静态成员,我敢打赌这个问题一开始就不存在。

【讨论】:

  • 优秀。谢谢。这正是我所需要的。现在我看到了我不知道为什么我自己无法解决的解决方案。 (没有需要数组参数的函数,因此以上是所需更改的总和。)
  • 我认为我最初回答的评分不公平。在 99% 的情况下,使用引用而不是普通指针更智能、更安全。
【解决方案2】:

核心问题是sizeof(A)>=150sizeof(B::name) < 150sizeof(B::address) <150。也就是说,B 使用的两个数组都不足以容纳单个 A 对象。因此,您需要为 A 分配一个连续的 150+ 字节。

如前所述,并没有真正的需要。没有真正的理由A 需要连续存储;它可以使用char* namechar* address。它们可以指向B 的两个缓冲区。是的,这是一个杂牌。是的,kludges 是您在 Arduino 等动力不足的系统上使用的。在实际系统上,您只需在libAlibB 上调用dlopen(),但不能同时调用两者。未加载的库不使用内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 2019-04-02
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    相关资源
    最近更新 更多