Using Tracking Reference to Pass array<> by Reference to a Native Class Method in C++/CLI

I was recently working with a .Net Application Developer who had a requirement to pass an array<int> member of a managed class to an native class method in C++/CLI to allocate the array and update it.

 

His original implementation was as follows.

   //managed class
   #pragma once
   
   ref class CMA
  {
  public:
        CMA(void);
   
        array<int>^ Seq;
  };
   
 //Native class
   #pragma once
   
   #include <gcroot.h>
  #include "MA.h"
   
  class CNB
  {
  public:
        CNB(void);
        ~CNB(void);
   
        void Calculate(gcroot<array<int>^> ar);
 };
   
 //Native class method implementation
   
   void CNB::Calculate(gcroot<array<int>^> ar)
    {
        ar = gcnew array<int>(1);
   
        ar[0] = 1;
   }
   
  //Here is how he invokes the method in main
   #include "stdafx.h"
  #include "MA.h"
  #include "NB.h"
   
  int _tmain(int argc, _TCHAR* argv[])
   {
        CMA^ ma = gcnew CMA();
   
        CNB nb;
   
        nb.Calculate(ma->Seq); //The call doesn’t update ma->Seq
   
        return 0;
 }

 

While stepping through the code we see the array is allocated in the native method but upon returning from it, the passed in variable doesn’t retain the updated values/allocation and he wanted a solution to this problem

 

To resolve the issue, we modified the signature of the native method as follows to use tracking reference .

 

 

 void CNB::Calculate(array<int>^% ar) 
{
 
       ar = gcnew array<int>(1); 
 
       ar[0] = 1;
 
}
 

 

After this we could see the array is allocated and modified in the called native function and the values were retained the main

 

Also note that we don’t have to use gcroot<> as in his original implementation, as we are dealing with managed types already. (The only reason to use gcroot is when you need to store a managed handle inside a native type.)