Reputation: 49
sorry if the question is too general, but I would like to know what is the best solution.
I have two projects. The main one is in C++ and needs to receive some information from a software component. For this it uses a .NET dll which I wrote in C# and receives the information from the software component using .NET libraries. I will write a simple CLI project to get the information that my C# project gets.
So, my problem is that the C# project has a lot of subscriptions to events and needs to receive asynchronously information from the software component. So, I don't know how to trigger an action in C++ (my main project which uses this .NET dll to ask for information from the software component) to save all data that has been collected at that point.
For instance, I have this event subscription in the C# project:
private void SubscribeMessages()
{
comm.Comms.Subscribe(new Action<LoadFilterEVENTMessage>(LoadFilterEVENT));
}
private void LoadFilterEVENT(LoadFilterEVENTMessage msg)
{
FilterValue = msg.Filter;
}
So, I would like that this LoadFilterEVENT let C++ know that it already has the filter value. Any hint?
Thank you in advanced :)
Upvotes: 1
Views: 641
Reputation: 1368
Here a solution :
1- Your C# dll need to load a C++ SubscribeMessages DLL which will be used to notify the program using the method DispatchEvents
:
using System.Runtime.InteropServices;
namespace MyCSharpDLL
{
class PlatformInvokeTest
{
// Import C++ DLL
[DllImport("SubscribeMessages.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void DispatchEvents();
static void LoadFilterEVENT(/*LoadFilterEVENTMessage msg*/)
{
//FilterValue = msg.Filter;
DispatchEvents();
}
/* Methods in DLL being used below */
public static void Main()
{
LoadFilterEVENT();
}
};
}
2- The function DispatchEvents
belongs to SubscribeMessages.dll
(simple C ++ dll project) has the role of releasing a binary semaphore to unlock the C++ program :
extern "C" __declspec(dllexport) void DispatchEvents()
{
// Juste open Semaphore
HANDLE ghSemaphore = OpenSemaphore (SEMAPHORE_ALL_ACCESS , TRUE, _T("SemSubscribeMessages"));
if ( NULL == ghSemaphore)
{
MessageBox(NULL,_T("Error when opening semaphore"),_T("Error"),0);
return;
}
// Release semphare in order that CPP program can be notified
ReleaseSemaphore(ghSemaphore, 1, NULL);
}
Finally, your C ++ program must wait on the SemSubscribeMessages
semaphore to be able to receive notifications.
As the wait is blocking, I put the WaitForSingleObject
function in a separate thread which allows more flexibility for your main program :
#include <windows.h>
#include <iostream>
using namespace std;
// Init value = 0 to block on the first call
#define INITIAL_COUNT 0
// Max value 1 to be a binarySemaphore
#define MAX_SEM_COUNT 1
DWORD WINAPI ListenNewEvent (LPVOID lpParam )
{
DWORD dwWaitResult;
HANDLE ghSemaphore = CreateSemaphore( NULL, INITIAL_COUNT, MAX_SEM_COUNT, _T("SemSubscribeMessages"));
if ( NULL == ghSemaphore) return -1;
while (true)
{
cout<< _T("Wainting for new Events ...")<<endl;
dwWaitResult = WaitForSingleObject( ghSemaphore, INFINITE);
MessageBox(NULL,_T("New Event arrive ..."), _T("Notification"),0);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwThreadId;
HANDLE hListnerThread = CreateThread( NULL, 0, ListenNewEvent, NULL, 0, &dwThreadId);
WaitForSingleObject (hListnerThread, INFINITE);
return 0;
}
Result:
When you run the main CPP programme, you get :
After C# dll send a notification, you will get:
If your need is to share data too (in addition to events) you can add a "shared memory" layer after the notifications ... hoping this helped you
Upvotes: 2