简体   繁体   中英

Pass C# array of object to C++/CLI

I'm force to expose some methods in a C# library so that they can be used from an external program written in C++ (VC++ 6.0). I thus created a mixed assembly which works quite ok so far but I have some troubles with a method that returns an array of .NET objects.

The .NET signature of the method is:

public Results[] Measure(String model, String identifier);

Where Results itself is:

public class Results
{
    public String[] ElementType;
    public bool[] HasError;
}

To provide entry point from C++, I started to write a C++/CLI wrapper method like this:

std::vector<ResultsWrapper> Measure(char* model, char* identifier)
{
    // Call .NET code
    String^ gcmodel = gcnew System::String(model);
    String^ gcidentifier = gcnew System::String(identifier);
    cli::array<Results^>^ gcres = myNetInstance->Measure(gcmodel, gcidentifier);

    // Convert results to C++ vector
    std::vector<ResultsWrapper> ret;
    for (int ki = 0; ki < res->Length; ki++)
    {
        ResultsWrapper r = ResultsWrapper(res[ki]->...., );
        ret.push_back(r);
    }

    return ret;
}

but I must admit I'm a bit lost, this is very long time I haven't wrote a single line of C++ and very long time I haven't deal with by hand memory management...

What is the best solution to create ResultsWrapper class so that there will be no much need to care for memory management from C++ side. Maybe something like the following ?

class ResultsWrapper
{
   public:
      ResultsWrapper(vector<std::String> elementType, vector<bool> hasError)
      {
         this.ElementType = elementType;
         this.HasError = hasError;
      }

   public:
     vector<std:String> ElementType;
     vector<bool> HasError; 
}

NB: I don't think team on VC++ 6.0 side are aware of boost library or share_ptr types (and I'm not very knowledgable about them either). All C++ code is very classic C++ code style, not even using stdlib .

I could not pass safely/easily STL types across dll boundaries so I get back to old char** , and manual allocation/deallocation and It Just Worked...

IJW for a while only ... then I tried to check for when throwing exception from .NET back to the calling C++ application and then patatra ... need conversion to native exceptions ... that again cannot safely cross dll boundaries ...

Mixed mode assemblies sounded appealing to go from .NET to native but was an IJS experience in my case... I give up and will go through COM instead.

In C++/CLI I started to write a wrapper method like this:

No, you did not

public Results[] Measure(String model, String identifier);

has no resemblance in

std::vector Measure(char* model, char* identifier)

None.

There is no marshalling required in a C++/CLI reference class. Use String^ as pointer to string (instead of char*) and use array<ResultsWrapper>^ as pointer to a managed array.

There is no need to use a wrapper at all. Declare a class as managed reference (ref class) and you can call it from the .NET side because it is a .NET class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM