1

I am a bit confused on how to marshal below mentioned C++ object to c++/CLI. Could you give me some idea?

Native C++ Classes

class HeaderMessage {
    double timestamp;
    string ric_code;
}

class TradeMessage {
   double price;
   int size;
}

 class RFARecord
 {
public:
    RFARecord();
    HeaderMessage * hMsg;
    list<TradeMessage *> qMsgs;
 };

My C++/CLI classes look like this

    public ref class RFARecordRef
{
public:
    RFARecordRef();
    RFARecordRef(RFARecord *record);
    HeaderMessageRef hMsg;
    List<TradeMessageRef> tMsgs;
private:
    RFARecord *record;
};

    ref class HeaderMessageRef
    {
    private:
        HeaderMessage *hMsg;
    public:
        HeaderMessageRef(void);
    };

    ref class TradeMessageRef
    {
    private:
        TradeMessage *tMsg;
    public:
        TradeMessageRef(void);
    };

I am not sure if my approach is correct.

I read data from a text file and transfer this data in the form of RFARecords to my C# program.

What is the right way to wrap or marshal above data objects to C++/CLI which can then be consumed by my C# program.

Thanks in advance.

Regards, Alok

Alok
  • 3,160
  • 3
  • 28
  • 47
  • possible duplicate of [C++/CLI Mixed Mode DLL Creation](http://stackoverflow.com/questions/2691325/c-cli-mixed-mode-dll-creation) – Hans Passant Jan 04 '12 at 17:53
  • I have read the above post already. It helped me initially to setup the wrapper. I am already passed that point. I am able to wrap my native class in CPP/CLI layer which is working fine. My issue now is to marshal the data correctly. Basic issue is with marshalling of a list of structures (these structures contain basic adta types) – Alok Jan 05 '12 at 04:19

1 Answers1

1

If I understand correctly. Your biggest task is going to be marshaling the strings from c++ strings into System::String^ objects.

What your going to do is declare a method in the C++/CLI class that returns a type System::String^ like so:

System::String^ get_str_from_cpp()
{
   std::string str = ptr_to_native_cpp_class->get_str();
   System::String^ ret_str = std_str2sys_str(str);
   return ret_str;
}

The std_str2sys_str method looks like so.

static System::String^ std_str2sys_str(std::string std_str)
{
   System::String^ sys_str = gcnew System::String(std_str.c_str());
   return sys_str;
}

Of course you could use a char* to if you wanted to.

The "ptr_to_native_cpp_class" variable should be a class variable that points to an instance of your native c++ class. It appears you already have those.

There are also ways to marshal from the System::String^ to std::string or char* which are on the net. Hopefully this example helps though. You don't have to worry about marshalling basic types like ints or bools though, you can just return them directly from your C++/CLI layer to the C#.

To answer the question of marshalling an structure over to C++/CLI; I don't think there is a way to automatically marshal an entire custom structure, even if it is composed completely of basic types. What I do in my code is just write a wrapper object that has specific get methods for each data member like so:

//Native C++ class
class data_container
{
public:
   int var1;
   int var2;
}

//C++/CLI class
public ref class cli_data_container
{
public:
   get_var1() {return data_ptr->var1;}
   get_var2() {return data_ptr->var2;}
private:
   data_container* data_ptr;
};

If there is an automatic way to do this that would be nice, but we had an intern make these interfaces for us for a few dozen utility classes last summer and they get the job done.

Ian
  • 4,169
  • 3
  • 37
  • 62
  • 1
    Don't write your own `std_str2sys_str` function, use the `marshal_as<>` template provided with Visual C++. – Ben Voigt Jan 04 '12 at 18:08
  • 1
    @Ben, I suppose so. Is this available in VS2005, or only 08? By the way Alok, here is a link from CodeProject that lists marshal_as usage http://www.codeproject.com/KB/mcpp/OrcasMarshalAs.aspx – Ian Jan 04 '12 at 18:15
  • If it doesn't come with VS2005, I'm sure it can be downloaded and added. And there's an extended implementation found [here](http://marshal-as.net/) that handles even more types. – Ben Voigt Jan 04 '12 at 18:16
  • Thanks Ben and Ian. Above information helps a lot. But I dont have issue with marshalling basic string type. I am using my own template to convert native string to CLI later string. I am having problem in marhsalling RFARecord class which consits of a HeaderMessage Structure and a list of Trade Message structures. (These structures contain only basic types). Could you shed some more light on marshalling RFARecord structure? Thanks in advance. – Alok Jan 05 '12 at 04:22
  • in short: If i have a structure of basic datatypes, then how to marshal a structure containing an array of structures. – Alok Jan 05 '12 at 06:21
  • I've edited the answer to hopefully answer your question. You could make an array in C# of the wrapper class I give an example of. How you initialize the pointer to the native c++ class (data_container* data_ptr) is entirely dependent on your implementation. – Ian Jan 05 '12 at 19:26
  • 1
    @Alok, If you're looking to create an array of structures in C#, then you're going to have to create an array of the wrapper and add logic that will set the pointer to the native c++ type appropriately for each member in the array. – Ian Jan 06 '12 at 20:46