0

I have been given a C++ Library with a function that takes a parameter of list< pair< tstring, tstring>>. I need to create a C# shim for other developers to be able to use this library.

I understand that marshaling generic types is not allowed, so I wanted to know if I can pass in an array of structs which mimics the list of pairs in C++.

In order to test if this works, I made a simple C++ DLL which mimics the DLL I was given. I created the following function in my C++ Test DLL:

//In my C++ Test DLL
int MyFunction(list<pair<tstring, tstring>> &listParams)

In C#, I created the following Structure to mimic the pair of tstrings:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
struct myPair
{
    [MarshalAs(UnmanagedType.LPTStr)]
    public string Key;
    [MarshalAs(UnmanagedType.LPTStr)]
    public string Value;

    public myPair(string key, string val)
    {
        Key = key;
        Value = val;
    }
}

Here is also the PInvoke definition to my C++ function:

[System.Runtime.InteropServices.DllImport("MyTestLib.dll",  
CharSet = CharSet.Unicode, EntryPoint = "MyFunction")]
[return: MarshalAs(UnmanagedType.I4)]
public static extern Int32 MyFunction(
        [param:  MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
        ref myPair[] listParams);

Here is the code in my C# Test Shim:

    public Int32 MyFunctionTest(Dictionary<string, string> testData)
    {
        Int32 retCode = 0;

        try
        {
            List<myPair> transfer = new List<myPair>();

            foreach (var entry in testData)
            {
                transfer.Add(new myPair(entry.Key, entry.Value));
            }

            myPair[] transferArray = transfer.ToArray();

            retCode = NativeMethods.MyFunction(ref transferArray);

        }
        catch (Exception ex)
        {
        }
        return retCode;
    }

Although the call is successful (does not crash), in my C++ method, the data is garbled and invalid.

Does anyone know if this sort of mapping is even possible?

1
  • The answers to this question suggests to use a C++/CLI layer between C++ and C# when you use STL classes. See also this example and this answer Commented Feb 1, 2016 at 21:20

1 Answer 1

1

Thanks to Wimmel I was able to find the answer. It was to create a "CLR based Shim" which is a bridge between my C# and the C++ library.

Here is the code:

//This is a method in a shim class which takes the C# objects
//and translates them to the C++ types required in the C++ dll 
Int32 myClass::Method(Dictionary<System::String^, System::String^> ^args)
{
    Int32 retCode = 0;
    list<pair<wstring, wstring>> listParams;

    for each (KeyValuePair<String^, String^>^ kvp in args)
    {
        listParams.insert(listParams.end(), 
            make_pair(msclr::interop::marshal_as<wstring>(kvp->Key),
            msclr::interop::marshal_as<wstring>(kvp->Value))
                          );
    }

    //My C++ Method
    MyFunction(listParams);

    return retCode;
}

I tested this in my C++ libary and the passed in data went through correctly and ungarbled

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.