Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IPC between .NET and C++ applications

Tags:

c++

.net

ipc

Are there any libraries for inter-process communication (IPC) between a .NET application and a native C++ application?

like image 984
Dimitri C. Avatar asked Dec 17 '22 03:12

Dimitri C.


2 Answers

You can use Socket for simple communication. It's in the os so you don't need any new libraries. Detailed info in C++ Socket and C# Socket

If the interprocess communication is always going to be done on the same machine, named pipes is the way to go because they are faster than other options.

like image 53
beermann Avatar answered Dec 28 '22 22:12

beermann


A simple (though limited) IPC mechanism is the WM_COPYDATA message

You can easily use it to transmit a struct to a native application.

I use the following helper class :

public static class CopyDataHelper
{

    [StructLayout(LayoutKind.Sequential)]
    public struct COPYDATASTRUCT
    {
        private int _dwData;
        private int _cbData;
        private IntPtr _lpData;

        public int DataId
        {
            get { return _dwData; }
            set { _dwData = value; }
        }

        public int DataSize
        {
            get { return _cbData; }
        }

        public IntPtr Data
        {
            get { return _lpData; }
        }

        public void SetData<T>(T data) where T : struct
        {
            int size = Marshal.SizeOf(typeof(T));
            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(data, ptr, true);
            _lpData = ptr;
            _cbData = size;
        }

        public T GetData<T>() where T : struct
        {
            return (T)Marshal.PtrToStructure(_lpData, typeof(T));
        }
    }

    [DllImport("User32.dll")]
    private static extern bool SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);

    public const int WM_COPYDATA = 0x004A;

    public static bool Send<T>(IntPtr fromHwnd, IntPtr toHwnd, int dataId, T data) where T : struct
    {
        IntPtr ptr = IntPtr.Zero;
        try
        {
            COPYDATASTRUCT cds = new COPYDATASTRUCT();
            cds.DataId = dataId;
            cds.SetData(data);
            return SendMessage(toHwnd, WM_COPYDATA, fromHwnd, ref cds);
        }
        finally
        {
            if (ptr != IntPtr.Zero)
                Marshal.FreeHGlobal(ptr);
        }
    }

    public static COPYDATASTRUCT Receive(Message msg)
    {
        if (msg.Msg != WM_COPYDATA)
            throw new ArgumentException("This is not a WM_COPYDATA message");
        COPYDATASTRUCT cds = (COPYDATASTRUCT)msg.GetLParam(typeof(COPYDATASTRUCT));
        return cds;
    }

}

To catch the WM_COPYDATA message, you need to override WndProc :

    protected override void WndProc(ref Message msg)
    {
        if (msg.Msg == CopyDataHelper.WM_COPYDATA)
        {
            CopyDataHelper.COPYDATASTRUCT cds = CopyDataHelper.Receive(msg);
            if (cds.DataId == myDataId)
            {
                MyData data = cds.GetData<MyData>();
                msg.Result = DoSomething(data);
                return;
            }
        }

        base.WndProc(ref msg);
    }
like image 30
Thomas Levesque Avatar answered Dec 28 '22 22:12

Thomas Levesque