How to implement the COM interface of C # in C++

Aspire 81 Reputation points
2024-01-11T00:13:06.88+00:00

I have a .NET Framework binary that implements two COM interface classes, where one serves as a callback function. Now, I want to use the implemented C# COM interface in a C++ project. I know how to create an object of type IMyDotNetInterface2, but I'm not sure how to implement a COM interface of type IMyDotNetInterface.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MyInterop
{
    [Guid("03AD5D2D-2AFD-439f-8713-A4EC0705B4D9")]
    public interface IMyDotNetInterface
    {
        void Send(string message);
    }
	[Guid("04AD5D2D-2AFD-439f-8713-A4EC0705B4D9")]
    public interface IMyDotNetInterface2
    {
        void SetCallback(IMyDotNetInterface callback);
		string GetStatus();
    }
	[Guid("05AD5D2D-2AFD-439f-8713-A4EC0705B4D9")]
    public class MyDotNetInterface : IMyDotNetInterface2
    {
		private IMyDotNetInterface _callback;
        public void SetCallback(IMyDotNetInterface callback)
		{
			_callback = callback;
		}
		public string GetStatus()
		{
			return "OK";
		}
    }
}
#import "<Full Path>\com.MyInterop.tlb" named_guids raw_interfaces_only
void DotNetCom()
{
	CoInitialize(NULL);   //Initialize all COM Components
		
	// <namespace>::<InterfaceName>
	MyInterop::IMyDotNetInterface2Ptr pDotNetCOMPtr;

	// CreateInstance parameters
	HRESULT hRes = pDotNetCOMPtr.CreateInstance(MyInterop::CLSID_MyDotNetClass);
	if (hRes == S_OK)
	{
		BSTR str;
		pDotNetCOMPtr->ShowCOMDialog ();
	}

	CoUninitialize ();   //DeInitialize all COM Components
}
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,860 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,695 questions
{count} votes

Accepted answer
  1. Minxin Yu 11,581 Reputation points Microsoft Vendor
    2024-01-15T07:47:05.3666667+00:00

    Hi, @Aspire
    You could refer to example code link in the similar thread's question: How does implementing multiple COM interfaces work in C++? Below is a quick test

    // ConsoleApplication1.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    
    #import "......\bin\Debug\MyInterop.tlb" named_guids raw_interfaces_only
    #include <iostream>
    #include<combaseapi.h>
    #include"./Debug/MyInterop.tlh"
    
    
    struct MyClass:public  MyInterop::IMyDotNetInterface
    {
    public:
        virtual ULONG  __stdcall AddRef(void) override { return S_OK; }
        virtual ULONG  __stdcall  Release(void) override { return S_OK; }
        MyClass()
        {
    
      }
        virtual HRESULT  __stdcall  QueryInterface(REFIID riid, void** ppvObject) override
        {
            if (riid == __uuidof(IUnknown))
            {
                *ppvObject = (IUnknown*)this;
                return S_OK;
            }
            IID uid;
            IIDFromString(L"{C# interface GUID/IID}", &uid);
            if (riid == uid)
            {
                *ppvObject = (IDispatch*)this;// (IUnknown*)this;
                return S_OK;
            }
            if (riid == __uuidof(IDispatch))
            {
                *ppvObject = (IDispatch*)this;
                return S_OK;
            }
            return E_NOTIMPL;
        }
        virtual HRESULT  __stdcall GetTypeInfoCount(UINT* pctinfo) override { return S_OK; }
        virtual HRESULT  __stdcall GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override { return S_OK; }
        virtual HRESULT  __stdcall  GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override
        {
            *rgDispId = 1;
            return S_OK;
        }
    
        virtual HRESULT  __stdcall Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override
        {
           
            return S_OK;
        }
        virtual  HRESULT  __stdcall  ShowCOMDialog()
        {
            std::cout << "hello";
            return S_OK;
        }
    };
    
    
    
    void DotNetCom()
    {
        CoInitialize(NULL);   //Initialize all COM Components
    
        
        MyInterop::IMyDotNetInterfacePtr pDotNetCOMPtr;
    
        // CreateInstance parameters
        // e.g. CreateInstance (<namespace::CLSID_<ClassName>)
        HRESULT hRes =
            pDotNetCOMPtr.CreateInstance(MyInterop::CLSID_MyDotNetClass);
        if (hRes == S_OK)
        {
            BSTR str;
            pDotNetCOMPtr->ShowCOMDialog();
            //call .NET COM exported function ShowDialog ()
        }
    
        CoUninitialize();   //DeInitialize all COM Components
    }
    int main()
    {
        MyClass test;
        test.ShowCOMDialog();
       
    }
    
    
    

    Best regards,

    Minxin Yu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. RLWA32 45,326 Reputation points
    2024-01-15T10:11:34.93+00:00

    I have created two sample solutions using VS2022 17.8.3. Each solution contains projects for a C# Com Server, a C++ Com Server and a C++ test program. One solution (CppComCallback) defines and implements the C++ Com callback in the C++ COM server. The other (CppComCallback2) defines the callback interface in the C# Com Server and imports the type library into the C++ Com Server which implements the related interface. I thought that providing concrete examples would be simpler than trying to walk through the details of creating the C++ COM servers. If you have any additional questions, I'd be happy to answer them. Don't forget to unblock the zip files from Onedrive before you extract their contents. Also, run Visual Studio as Administrator when building the sample solutions so that COM registration will succeed.

    CppComCallback.zip

    CppComCallback2.zip

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.