locked
C++/CX Interop of structs from managed library (not a WinRT component)

    Question

  • Hi,

    I am trying to establish a data read/write between C++ Metro Application and a managed library. Because you cannot directly reference a managed library from C++ Metro App, I made a WinRT Component written in C# to act as a bridge between native code and C# managed land.

    And it works great, if I am trying to change struct which only consists of primitives types, but if a struct has a managed type, I don't know how to change that field from C++, and my question is - is that possible at all, or are there other methods. 

    Here's the code snippets to explains what I exactly mean, so like a said there are three modules:

    * C++ Metro App which has a code:

    struct StructA
    {
    	float a;
        float b;
    };
    struct StructB
    {
    	float a;
        float b;
    	Object^ o;
    };
    void ModifyMyStructA(int ptr)
    {
    	StructA* s = (StructA*)ptr;
    	s->a = 1.0f;
    	s->b = 3.0f;
    }
    void ModifyMyStructB(int ptr)
    {
    	// Never called
    	StructB* s = (StructB*)ptr;
    	s->a = 1.0f;
    	s->b = 3.0f;
    	s->o = nullptr;
    }
    
    void PerformCommunications()
    {
    	Utils::SetDelegateA(ref new ModifyMyStruct(ModifyMyStructA));
    	Utils::SetDelegateB(ref new ModifyMyStruct(ModifyMyStructB));
    	Utils::CreateAndChangeStructs();
    }

    * A WinRT component which is referenced from C++ Metro App:

    namespace Bridge { public delegate void ModifyMyStruct(int srcPtr); public sealed class Utils { internal static ModifyMyStruct modifyMyStructA; internal static ModifyMyStruct modifyMyStructB; public static void SetDelegateA(ModifyMyStruct _modifyMyStruct) { modifyMyStructA = _modifyMyStruct; } public static void SetDelegateB(ModifyMyStruct _modifyMyStruct) { modifyMyStructB = _modifyMyStruct; } public static unsafe void CreateAndChangeStructs() { Assembly assembly = Assembly.Load(new AssemblyName("ManagedLibrary")); Type structAType = assembly.ExportedTypes.First(t => t.FullName == "ManagedLibrary.StructA"); Type structBType = assembly.ExportedTypes.First(t => t.FullName == "ManagedLibrary.StructB"); object a = Activator.CreateInstance(structAType); object b = Activator.CreateInstance(structBType); GCHandle handleA = GCHandle.Alloc(a, GCHandleType.Pinned); modifyMyStructA(handleA.AddrOfPinnedObject().ToInt32()); handleA.Free();

    // A first change exception of type 'System.ArgumentException' occured in mscorlib.dll

    // Additional information: Object contains non-primitive or non-blittable data. GCHandle handleB = GCHandle.Alloc(b, GCHandleType.Pinned); modifyMyStructB(handleB.AddrOfPinnedObject().ToInt32()); handleB.Free(); } } }


    * And arbitrary managed library which is dynamically loaded from WinRT component: 

    namespace ManagedLibrary
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct StructA
        {
            float a;
            float b;
        }
    
        [StructLayout(LayoutKind.Sequential)]
        public struct StructB
        {
            float a;
            float b;
            object o;
        }
    }

    So as you see C++ Metro App doesn't know nothing about managed library, but I can acquire a pointer to a struct and map it to C++ struct, and succesfully read/write data, but I don't know how to achieve the same if struct has a managed type, I think it's possible in CLR, but I don't know how to achieve this with WinRT.

    Any suggestions? Workarounds? Or is that impossible?

    Thank you

    Friday, September 14, 2012 7:36 AM

All replies

  • Anyone?
    Sunday, September 16, 2012 6:49 PM
  • WinRT types are different from managed types. You can only pass fully-compatible WinRT types between WinRT components.
    Monday, September 17, 2012 4:46 PM
  • Well this is not totally true, I can have a function in third party managed assembly which returns an object, and on C++/CX it would be Platform::Object^ and it works quite fine :)

    But I don't know how to solve the issue with struct with managed type.

    Monday, September 17, 2012 4:52 PM