4

In C#, I defined a struct:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MyObject
{
   [MarshalAs(UnmanagedType.LPWStr)]
   public string var1;    

   [MarshalAs(UnmanagedType.LPWStr)]
   public string  var2;    
};

I have this struct in C++:

public value struct MyObject
{
    LPWSTR var1;    
    LPWSTR var2;    
};

And in the method of C++ which is a public class to be called from C#:

TestingObject(MyObject^ configObject)
{
   // convert configObject from managed to unmanaged.
}

The object is debugged correctly that I can see two strings var1 and var2. However, the problem now is that I need to marshal the object: configObject into an unmanaged object.

What I think of is to do something like this:

TestingObject(MyObject^ configObject)
{
   // convert configObject from managed to unmanaged.
   MyObject unmanagedObj = (MyObject)Marshal::PtrToStructure(configObject, MyObject);  
}

That is what I can think of but off course, I got this error:

Error 2 error C2275: 'MyObject' : illegal use of this type as an expression

Is that right to convert the managed object into unmanaged object? If so, how can I can that Marshal::PtrToStructure correctly? If no, how can I do it?

halfer
  • 19,824
  • 17
  • 99
  • 186
olidev
  • 20,058
  • 51
  • 133
  • 197

2 Answers2

3

Marshal::PtrToStructure does the opposite of what you want, it converts an unmanaged pointer to a managed object. You want Marshal::StructureToPtr.

Also, you would need to define an unmanaged class, because MyObject is a Managed Type. Assuming you have done that, you could do it like this (just converted this from the C# sample):

IntPtr pnt = Marshal::AllocHGlobal(Marshal::SizeOf(configObject)); 
Marshal.StructureToPtr(configObject, pnt, false);

You then have a pointer to the data, which you can memcpy or whatever into your native struct.

But MyObject is and will stay a managed type. If you want a truly unmanaged type, you have to define one that matches the managed struct.

Just wondering, why are you using unmanaged LPWSTR in a managed struct?

Botz3000
  • 39,020
  • 8
  • 103
  • 127
  • I Just have updated my question which includes also the object in C# and you can see that I define the same one in C++. You are right that I copy the managed object configObject to pnt. But how can I create an unmanaged ConfigObject from that pnt? Thanks in advance. – olidev Mar 23 '12 at 16:10
  • Those class definitions are both managed. Why are you not defining the class **only** in your C++ assembly and use that from C#? I mean you already referenced the library. Then you would be using the same class. – Botz3000 Mar 23 '12 at 16:18
  • I am not experienced with this topic to send a struct from C# to C++. So you mean I need to construct it in C++ first then use from C#. What should the struct definition in C++ be? could you please suggest me? Thanks in advance – olidev Mar 25 '12 at 19:51
  • It depends on what you want to do with it. Why does it need to be unmanaged? You could use the struct you already have in C++, but instead of LPWSTR, use String^. That way, you could use it from both C# and C++. – Botz3000 Mar 25 '12 at 20:18
  • well. I just have tried to update the struct both in C# and C++ as advised by Paul below. var1 will be String^. In order to print it, I have to it like this: printf((const char*)(Marshal::StringToHGlobalAnsi(myObject->var1)).ToPointer()); but I got an exception at that line – olidev Mar 26 '12 at 07:31
  • Why don't you try `Console::WriteLine(myObject->var1)` ? – Botz3000 Mar 26 '12 at 21:45
1

You probably mean:

struct MyUnmanagedStruct {
    LPWSTR var1, var2;
};

Then you can use Marshal.StructureToPtras suggested by Botz3000. Otherwise C#'s

public struct MyObject {
   public String var1;
   public String var2;
}

and C++/CLI's

public struct value MyObject {
   public String^ var1;
   public String^ var2;
}

are completely equivalent, assuming your're you're using the same System.String on both sides.

Paul Michalik
  • 4,331
  • 16
  • 18
  • thanks. Because I asked another question: http://stackoverflow.com/questions/9651585/how-to-set-an-object-into-c-from-c-sharp and they suggested to use LPWSTR. For your other solution, I need to convert String^ to string in C++, right? – olidev Mar 25 '12 at 19:49
  • Hm, no or yes... since I am not sure what you are up to right now. In the other thread you asked how to make a .NET object available to native c++. Yes, the answer you got there is a possible way, though not the most elegant, nor the safest. From what you've posted here, it appears as you were trying to do something strange: store unmanged strings in a managed value type `public value struct MyObject`... – Paul Michalik Mar 28 '12 at 15:20