TVaComm in a DLL

I've been working on a project where multiple TVaComm's objects are created within a DLL.  The OnRxChar event is also in the DLL.  The purpose of the DLL is to handle all incoming data and to convert the inbound data to a common format (JSON) and pass it back to the main program via window messages. (This works now). This will allow us to redistribute newly created dlls without having to test/redeploy the main application as long as the JSON is compatible in the DLLs.


The TVaComm object gets created successfully within the DLL.  However, when data is sent to the comport, the OnRxChar event is never fired until the DLL is about to be unloaded from memory (when the main app closes).  

I've used the TVaComm objects for several years, but never within a DLL.  Is there something obvious prohibiting the object from working as it does in the main application thread or working in the same manner in a DLL?

Thanks for any assistance.
Jim

TVaComm's receiving of data is based on receipt of a message via the Windows message loop. That means that TVaComm needs to have an owner that has a window handle & handles the Windows message loop. As such, without setting up such construction in the DLL, OnRxChar will indeed not trigger.

Thank you Bruno for your response.


I've added a TForm to the DLL and create it using the Application.CreateForm(TForm, fForm) and then pass the fForm to 

Application.CreateForm(TForm, fForm);
fComPort := TBCSVaComm.Create(fForm);

This doesn't seem to work.  I believe it is because the instance  of 'Application' is NOT the main app, but of the DLL.  

I'm assuming, then, any form needs to be passed to the DLL.  Does that make sense to you or is this completely going about solving the separation of the comport objects from the main application completely wrong?

I really want the 'intelligence' in the DLL since the data will always coming in to the comports in many different formats.  The DLL will then post the data to the main application form as JSON and will always be a uniform data format.  Having this in a dll allows us to just rewrite a new dll and deploy separately.

Any guidance is appreciated.

Thank you.

Is the form having a valid window handle?

I.e. , does form.HandleAllocated return true?
 When I initialize the DLL, I pass the Application.Handle of the calling app to it  Then, within the DLL, I set it to the DLL's Appication.Handle  as seen below.

The fform displays along with the button.  However, fform.HandleAllocated  test doesn't return true until the 'Show' method is called.  Regardless, the TVaComm never receives the  ComPortRxChar when data is sent to the ComPort.  In the next day or so, can I send you a sample exe/dll project showing the issue?  It may be easier to see exactly what I'm doing.


  Application.Handle := self.AppHandle;
  fForm := TForm.Create(Application);

  fform.Caption := 'init_comport';
  btn := TButton.Create(fform);

  btn.Parent := fform;
  btn.Left := 10;
  btn.Top  := 100;
  fForm.show;
  btn.Caption := 'press me';
  if fform.HandleAllocated then
    ShowMessage('Yeah')
  else
    ShowMessage('boooooooo');


  if fComPort = nil then
    begin
      fComPort := TVaComm.Create(fForm);
      fComPort.PortNum  := aPort;
      fComPort.AutoOpen := True;
      fComPort.ASTM     := aASTM;
     fComPort.OnRxChar := ComPortRxChar;

      try
      fComPort.Open;
      except
      on e: exception do
        sendMessageOut(dtMessage, e.Message);
      end;
    end;
In reference to the code snip it above,  the order in which 'Show' is called determines whether 'fForm.HandleAllocated' returns true or false.   I don't understand why......

HandleAllocated returns TRUE
----------------------------------------- 
 fForm.show;
  btn.Caption := 'press me';
  if fform.HandleAllocated then
    ShowMessage('Yeah')
  else
    ShowMessage('boooooooo');


HandleAllocated returns FALSE
----------------------------------------- 
  btn.Caption := 'press me';
  if fform.HandleAllocated then
    ShowMessage('Yeah')
  else
    ShowMessage('boooooooo');
  fForm.show;

The handle is created when your form is being shown, so the above is correct, HandleAllocated is false when the form is not yet shown the first time.

Thanks.  I sent an email with an attached zip containing a project and dll source for what I'm trying to accomplish.  It demonstrates the problem I'm having.


Thank you.

@Bruno: I have the same problem as Jim. Would it be possible for you to paste some code to show us how to create the window with a handle and the message loop that handles the OnRxChar event.

Thank you very much.

Easiest would be to programmatically create a TForm instance and then programmatically create a TVaComm instance and make sure owner of TVaComm is the created TForm.

Thanks for the answer Bruno. I've tried what you suggested and I'm afraid I still don't have any luck.

The following gets done when the DLL gets created:




frmHiddenWindow := TForm.Create(nil);
frmHiddenWindow.WindowState := wsMinimized;
frmHiddenWindow.Show;
VaComm1 := TVaComm.Create(frmHiddenWindow);
VaComm1.OnRxChar := VaComm1RxChar;


The OnRxChar ONLY gets fired when I destroy the DLL on the way out. The information read from the port is correct, but I only see it when the DLL is closing.

What am I missing?

Thanks.

@Bruno. Any suggestions?

Hello Faiga Charles

Do you have already found a solution for this
problem? I need really support for this but currently it seems Bruno
Fierens is not available?

Thanks a lot for your quick reply!

I wasn't able to get the TMS component to work within a DLL, so I tried TApdComPort (the opensource TurboPower components).  I had used these before in other projects and the TRIGGERS was more complex than what I needed at the time (TMS is no doubt easier to work with), but I was able to get Async capabilities into a DLL with TApdComPort  and without needing a form.  I still love TMS tools.

oh ... I see.. And I agree with you... I really need to get this to work with the TVaComm. BTW is the TApdComPort not already very outdated and non-supported?

Sorry, I haven't been able to allocate time for this yet. I have given the hint to solve this issue with a TForm based on the feedback of another customer who told me he
solved the issue this way but I have not done this exact implementation myself
yet.

<o:p></o:p>

Hello Bruno

As you can see Jim, Charles and myself haven't got to work this with a workaround through the TForm idea. Can you please find some time to check it by yourself and tell us a hotfix and/or working workaround for the usage inside a DLL. I guess it has something to do with the wrong message handling?!

I really already have a big time problem.

You quick help will be appreciated!

Hi Gossens Kai,

I still haven't found a way to solve this problem. I too have to use TVaComm only.

Hey Charles

I tried to get a little deeper into this problem. And Bruno from TMS is currently to busy... Not really a good support for this problem right now anyway. :(

So it seems that the CreateEvent function doesn't work properly inside a DLL. So maybe you can try it yourself to debug a little inside the TVaCommEventThread ... It seems the WaitCommEvent hangs inside a DLL until it will be freed/destroyed.

Hope you can help me out... Maybe we both can get it to work together?

@Bruno:
Please take a look too. We both really need a very urgent solution here... Thanks!

Best regards

It's on my todolist. As I explained, I do not have a ready to use sample here and will need to investigate this myself but we're also at this time snowed under with work related to the Delphi 10 release for which everyone asks support for.