Visual Studio - 使用 /clr 选项 => 函数编译嵌入式代码的 C++14 无法按托管方式编译。 C2711, C3820

Visual Studio - C++14 compiling embedded code with /clr option => function cannot be compiled as managed. C2711, C3820

在一个软件在环测试环境项目中,我使用 VisualStudio2019 编译嵌入式软件(C++14,使用 etl(嵌入式模板库)) VisualStudio 单元测试 (C#)。 因此,嵌入式软件位于 (stubbed/mocked) HAL 和 OS 层,并使用 CLR 支持 (/clr) 进行编译。现在我被困在一个我慢慢生气的地方:-(

在嵌入式软件中,状态机由特定的 classes 实现。一个class有一个etl::stack类型的成员,它实现了一个固定大小的栈。固定大小的栈在etl中实现为对齐存储。

现在出现了 VisualStudio 编译器,抱怨:

C2711 函数无法编译为托管,请考虑使用#pragma unmanaged。托管代码不支持对齐的数据类型。

C3820 dataExchangeContainer:必须管理初始化器

我已 'cut' 将相关代码输出到一个新项目以深入了解此问题的详细信息,以了解我可以做些什么来编译它。下面是示例代码。您需要下载嵌入式模板库并将其放入您的项目中,以使这段代码在编译器错误中绊倒。

#include "etl/array.h"
#include "etl/array_view.h"
#include "etl/optional.h"
#include "etl/stack.h"

//SendDataState.hpp
class SendDataState
{
  static constexpr std::size_t amountOfDataToSend = 3u;
  etl::optional< etl::stack<etl::array_view<const uint8_t>, amountOfDataToSend> > _data;
};

//DataExchange.hpp
class DataExchange
{
  SendDataState _sendDataState;
};

//SomeInlineImplementation.hpp
static constexpr std::uint8_t dataExchangePoolSize{ 1U };
etl::array<DataExchange, dataExchangePoolSize> dataExchangeContainer{ DataExchange{} };
etl::array_view<DataExchange> dataExchangeContainerView{dataExchangeContainer};
   
int main()
{
  return 0;
}

困扰我的代码行是主例程上方的 etl::array<...> dataExchangeContainer{..}。将 DataExchange 放入 etl::arry 会导致编译错误。如果只是创建 DataExchange 的一个实例而不将其放入数组中,它可以正常编译。 另外要说的是,没有激活编译器优化!

我在 _data(SendDataState class)的定义以及 class 本身的周围放置了一些 #pragma managed(push, off)/#pragma managed(pop)。我只是没有编译它。作为一种绝望的行为,我也将 pragmas 放在 etl::stack 的定义上。没有任何帮助。我已经阅读了有关 clr 和本机 c++ 的文档,据我了解这个主题,应该可以获得这个混合 clr/native 代码 运行。但是,我觉得我在盯着空白的墙,相当代码盲。

尽管使用 /clr 支持(项目要求)进行编译,但对嵌入式代码“更改”的影响应该尽可能小,以便编译。

非常感谢任何提示和想法!

非常感谢您的帮助!

我终于找到了编译的方法。

我不得不通过将数组初始化放入由 pragma managed 修饰的函数中来修改代码(小修改),见下文。现在编译正常了!

用 pragma 修饰像数组初始化这样的单个语句是行不通的,它必须是一个函数。至少在我看来是这样。

这里是附加代码:

#pragma managed(push, off)
decltype(auto) createDataExchangeContainer(){
  return etl::array<DataExchange, dataExchangePoolSize> dataExchangeContainer{ DataExchange{} };
}
#pragma managed(pop)

最后初始化数组视图:

decltype(auto) dEContainer = createDataExchangeContainer();
etl::array_view<DataExchange> dataExchangeContainerView{createDataExchangeContianer{dEContainer}};

我相信还有更优雅的方式来表达这一点,但目前有效,美化稍后

:-)