c++-cliclrvisual-c++-2015

Retrieving data in Managed Heap from UnManaged Heap


This my first post in StackOverFLow!

I'm trying to understand C++/CLI, I have an unmanaged struct with two properties getLx and setLx, which retrieves a pointer to double and accepts a pointer to double respectively. So I'm populating the values in setLx in an Unmanaged method, and trying to retrieve the values from getLx in Managed scope. I want to convert or get data that is allocated on unmanaged heap to managed heap.

So basically in below example code, I need double^ reference type from native double* native pointer reference type

 /*Unmanaged Struct*/
    struct Grid2D
        {
        double* getLx() const {
            return _Lx;
            }
        void setLx(double* val) {
            _Lx = val;
            }
        private:
            double* _Lx;
        public:
            int _count;
        };

    #pragma unmanaged
    void UnmanagedFillGrid(Grid2D& d)
        {
        printf_s("\nunmanaged");
        double* item = new double[d._count];
        int i = 0;
            while (i++ < d._count) {
                int r = (rand() % 100) + 1;
                item[i] = r;
                printf_s("array[%d] = %f\n", i, item[i]);
                }
            d.setLx(item);
        }

    #pragma managed  
    int main(array<System::String ^> ^args)
    {
        Grid2D d;
        d._count = 10;
        UnmanagedFillGrid(d);   
        Console::WriteLine("[managed] count = {0}", d._count);
        //getLx returns pointer to double, I need to get in double^
        //Is this possible ?
        double^ managedLx = d.getLx();//How to convert ?? 


        return 0;
    }

Solution

  • First: Although it's a valid type in C++/CLI, you shouldn't use double^. A managed reference to a value type is weird, unnecessary, and doesn't exist at all in other .Net languages (e.g., C#).

    So, it looks like your double* is an array. The managed array type is array<double>^, not double^. That is what you should use on the managed side. The managed array also knows its own length, so you don't need to expose the count separately.

    In order to move the data from the double* to the array<double>^, it needs to be copied. There is no way to create the array object such that it uses memory that has been allocated by something else, so copying the data is the only possibility. You can use either the Marshal::Copy method, or use a for loop and copy the data yourself. (They boil down to the same thing.)