Search code examples
.netstructc++-climarshalling

How to marshall a managed cli::array<byte>^ into a managed structure?


On C/CLI I´m trying to build a function that will convert a byte array buffer received from a managed class to a managed structure. The structure has some enums on its composition. Here is my code:

  public enum class ControlEnum {
        LOCAL,
        REMOTE,
        EMERGENCY,
        ERROR
    }


    public enum class StateEnum {
        ON, 
        OFF
    }

    public enum class TimeoutEnum {
        10SEC,
        30SEC,
        1MIN,
        5MIN
    }

    public enum class StatusEnum {
        OK,
        FAILURE
    }

    public ref struct ReportDataStruct{
        public:
             ControlEnum control;
             StateEnum state;
             TimeoutEnum timeout;
             Single value;
             Int32 attenuation;
    };

    public ref struct ReportStruct {
        public:
            StatusEnum reportStatus;
            DateTime reportDataTime;
            cli::array<byte>^ reportData;
    };

what I need is to map the reportData field from the ReportStruct into the ReportDataScruct to be used by the application. By having a structured type I can access direct its fiels on the application;

In plain C++ I would build a simple function like:

ReportDataStruct& convert(ReportStruct& report)
{
    return (ReportDataStruct&) report.reportData;
}

What would be the equivalent on C++/CLI considering both structures are managed itens ? I´ve found examples using System.Interop.Marshall and pin_ptr, but I don´t know exactly where to go.


Solution

  • To summarize the new information from the comments, as I understand it:

    • The byte array arrives over the network.
    • The byte array is generated by some embedded C++ code (in other words, not using the .Net class that your code uses).
    • The byte array can be converted to several possible classes, of which ReportDataStruct is just one possibility.

    Your choices are to write some methods to convert byte arrays into .Net objects, or have something in the .Net framework do that conversion for you. There is no way to take a byte array's memory and directly use it as a managed reference type.

    Given those two choices, I would choose to do the conversion myself, because it's much easier to verify that it's correct. To get the .Net framework to do the conversion, you're going to have to spend time with the attributes in the InteropServices namespace in order to make the Marshal class use the same memory representation as the embedded C++ code does. If the representation is slightly off, it would be easy for subtle bugs to creep in, which is less likely with an explicit Deserialize method.