in an Software-in-the-loop test-environment project I use VisualStudio2019 to compile embedded software (C++14, with etl (embedded template library)) for the VisualStudio Unittests (C#). Hence, the embedded software is (stubbed/mocked) at the HAL and OS-Layers and compiled with CLR support (/clr). Now i am stuck at a location where I am slowly getting mad :-(
In the embedded software a state machine is implemented by specific classes. One class has a member of type etl::stack, which implements a stack of fixed size. The fixed-sized stack is implemented in the etl as an aligned storage.
Now comes the VisualStudio compiler, complaining about:
C2711 Function cannot be compiled as managed, consider using #pragma unmanaged. Aligned data types not supported in managed code.
C3820 dataExchangeContainer: Initializers must be managed
I have 'cut' out the related code to a new project to get into details for this issue, to understand what i can do to get this compiled. Below is the example code. You need to get the embeded template library downloaded and put into your project to get this code stumbling over the compiler errors.
#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;
}
The codeline that is bugging me is the etl::array<...> dataExchangeContainer{..}
above the main routine. Putting the DataExchange
into the etl::arry
leads to compiling errors. If just create an instance of DataExchange
without putting it into the array, it compiles fine.
Additional to say, there are no compiler optimizations activated!
I have put some #pragma managed(push, off)/#pragma managed(pop)
around the definition of _data
( SendDataState class) as well as the class itself. I just do not get it compiled. As an act of desperation I had put the pragmas on the definition of etl::stack too. Nothing helps. I have read the documentation regarding clr and native c++ and as far as i have understood this topic it should be possible to get this mixed clr/native code running. However, I feel i am staring at blank wall, quite code-blind.
Although compiling with /clr support (project requirement) the impact on "changes" to the embedded code should be as little as possible to get it compiled.
Any hints and ideas are highly appreciated!
Thank you very much for you help!
Finally I found a way to get things compiled.
I had to modify the code (minor modification) by putting the array initialization into a function which is decorated by pragma managed
see below. Now it compiles fine!
Decorating a single statement like the array initialization with the pragma doesn't work, it has to be a fuction. At least it looks to me that way.
Here the additional code:
#pragma managed(push, off)
decltype(auto) createDataExchangeContainer(){
return etl::array<DataExchange, dataExchangePoolSize> dataExchangeContainer{ DataExchange{} };
}
#pragma managed(pop)
finally initialize the array view:
decltype(auto) dEContainer = createDataExchangeContainer();
etl::array_view<DataExchange> dataExchangeContainerView{createDataExchangeContianer{dEContainer}};
i am sure there are more ellegant ways to express this, but it works for now, beautifying comes later
:-)