How can I pass a C++ struct to a C# DLL method using COM interop

47 views Asked by At

I currently have a C# project which is compiled into a COM interop DLL containing the following:

using System.Runtime.InteropServices;

namespace CommonTest
{
    [ComVisible(true)]
    public interface ICommonTest
    {
        [DispId(1)]
        int Test(int a, int b);
    }

    [ComVisible(true)]
    public class CommonTestManaged : ICommonTest
    {
        /// <summary>
        /// A method to test the creation of a managed DLL built in C#. It's functionality just adds together two numbers.
        /// </summary>
        /// <param name="a">Number 1</param>
        /// <param name="b">Number 2</param>
        /// <returns>The sum of numbers a and b</returns>
        public int Test(int a, int b)
        {
            return a + b;
        }
    }
}

On the C++ side, this method is successfully called with the following:

void Usage()
{
    CoInitialize(nullptr);
    ICommonTestPtr pICommonTest(__uuidof(CommonTestManaged));

    long lResult = 0;
    pICommonTest->Test(5, 10, &lResult);

    CoUninitialize();
}

My question is, is there a way to pass a C++ struct as an parameter of Test() so that I can access its contents in C#?

1

There are 1 answers

2
Simon Mourier On BEST ANSWER

It depends on the struct definition and types (it must describable by a type library), but yes, you can create a struct like this in C#

[ComVisible(true)]
[StructLayout(LayoutKind.Sequential)]
public struct Test
{
    public int Value1;
    public int Value2;
    etc...
}

Use it like this in the interface (and implement it in the class):

[ComVisible(true)]
public interface ICommonTest
{
    void Test(ref Test test);
}

The Visual Studio #import directive will generate code like this in the .tlh file:

struct __declspec(uuid("d80d27a3-7643-39bf-bba8-c8cc0ab10e7e"))
Test
{
    long Value1;
    long Value2;
    etc...
};

And you can use like this in C++:

ICommonTestPtr pICommonTest(__uuidof(CommonTestManaged));

Test t = {};
t.Value2 = 123456789;
pICommonTest->Test(&t);