0

There's this external function I call in order to receive data updates from a DLL. The DLL basically sends something as soon as sth gets updated on the DLL side.

// Definition:
partial class DLLConnector
{
    // Initializing the DLL:
    [DllImport(dll_path, CallingConvention = CallingConvention.StdCall)]
    public static extern sbyte InitializeDLL(TUpdatedDataCallback updateDataCallback);
    
    // External function that generates the updated messages:
    [DllImport(dll_path, CallingConvention = CallingConvention.StdCall)]
        public static extern sbyte GetDataUpdate([MarshalAs(UnmanagedType.LPWStr)] string dataToBeSubscribed);
    
    // Delegate handling:
    public delegate void TUpdatedDataCallback([MarshalAs(UnmanagedType.LPWStr)] string updatedData);
    public static TUpdatedDataCallback _updatedDataCallBack = new TUpdatedDataCallback(DataUpdateCallback);
}

// DLL can be called by GetData():
partial class DLLConnector
{
    string activeDataPipeName = "dataPipe1";

    public static void GetData(string dataPipeName)
        sbyte retVal = GetDataUpdate(activeDataPipeName) // retVal: just an info whether the call was made successfully or not
}

A delegate is properly declared in order to handle the message received from the DLL (which, by the way, is being shown here a simple string just for the sake of simplicity) and I'm able to process it with the following function:

public static void DataUpdateCallback([MarshalAs(UnmanagedType.LPWStr)] string updatedData)
{
    Console.Writeline(updatedData); // This is working fine
    // Other code
}

What I'm trying to do is to store this data by adding each message received from the DLL to a List that is declared somewhere outside the callback function declaration.

The GetDataUpdate function only returns an sbyte that informs whether the call to the DLL has successfully been made, so there's no way to handle this by using its return.

My understanding is that, once the DLL calls DataUpdateCallback every time there's an updated message to be sent over, it wouldn't make a sense to create an instance of some Class within its code block (as shown below), as this would be instantiating a similar object (and with the same name) everytime the DLL calls this function.

public static void DataUpdateCallback([MarshalAs(UnmanagedType.LPWStr)] string updatedData)
{
    Console.Writeline(updatedData);
    MessageReceived messageList = new();
    messageList.AddMessage(a);
}

class MessageReceived
{
    List<string> messages;
    public MessageReceived()
    {
        messages = new();
    {
    public void AddMessage(string a)
    {
        messages.Add(a);
    }
}

Could anyone assist, please? I'm not sure how to figure out this scoping issue, so I could store these messages and allow other functions to retrieve those from the List.

Thanks!

roccaforte
  • 81
  • 5
  • 1
    How is your dll going to call your callback if there is no way to pass that callback to it in the first place? – GSerg Nov 24 '21 at 14:19
  • 2
    `there's this external function I call in order to receive data updates from a DLL.` I don't see that in the following code. Thats just a method defined that you can call on the Dll. When you want something registered for callbacks that function would need to return a function pointer (a callback) that you can connect with a .net delegate. – Ralf Nov 24 '21 at 14:19
  • @Gserg I've just updated the original message in order to make it more clear – roccaforte Nov 24 '21 at 14:59
  • @Ralf, thanks. I've just updated the original message in order to make it more clear – roccaforte Nov 24 '21 at 15:00
  • 2
    @roccaforte I still don't see where you connect the DataUpdateCallback with something coming from the dll. – Ralf Nov 24 '21 at 15:15
  • 1
    You are passing a mere string to your dll. There is no way this may result in `DataUpdateCallback` being called by the dll. Assuming the `"dataPipe1"` is the name of a [named pipe](https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipes), you should [use corresponding .NET classes](https://stackoverflow.com/q/13806153/11683) to read from it, but at no point your `DataUpdateCallback` will be called. – GSerg Nov 24 '21 at 15:29
  • @Ralf what you said made me notice something I was missing, but I'm still not able to store it (just updated the original post)... I'm guessing the problem might be something with the 'void' return in the delegate declaration, but I'm not really sure. – roccaforte Nov 24 '21 at 16:00
  • Hi @GSerg. Yeah, you were right. That helped but there may be something else I'm missing here. I'm stuck. BTW, 'pipe' here does not refer to a named pipe. – roccaforte Nov 24 '21 at 16:01
  • 2
    We are getting closer ;) And you call InitializeDLL somewhere and hand over the _updatedDataCallBack delegate? – Ralf Nov 24 '21 at 16:09
  • Thanks, @Ralf! InitializeDLL is being called directly in the Main function. When it comes to _updatedDataCallBack, this is currently only being used by a GC.KeelAlive(_updatedDataCallBack) method somewhere else, but I think I can see where you are trying to get... ;) ... A multiple delegate declaration in the Main function, say, '_updatedDataCallBack += _updatedDataCallBackForStorage'? – roccaforte Nov 24 '21 at 16:28
  • @Ralf, nevermind my guess... A multiple delegates basically replicates the same difficulty I'm facing. It was a naive guess. – roccaforte Nov 24 '21 at 21:29

0 Answers0