Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to start (and stop) a thread inside a DLL?

I'm pondering some ideas for building a DLL for some common stuff I do. One thing I'd like to check if it's possible is running a thread inside of a DLL. I'm sure I would be able to at least start it, and have it automatically free on terminate (and make it forcefully terminate its self) - that I can see wouldn't be much of a problem. But once I start it, I don't see how I can continue communicating with it (especially to stop it) mainly because each call to the DLL is unique (as far as my knowledge tells me) but I also know very little of the subject.

I've seen how in some occasions, a DLL can be loaded at the beginning and released at the end when it's not needed anymore. I have 0 knowledge or experience with this method, other than just seeing something related to it, couldn't even tell you what or how, I don't remember. But is this even possible?

I know about ActiveX/COM but that is not what I want - I'd like just a basic DLL that can be used across languages (specifically C#).

Also, if it is possible, then how would I go about doing callbacks from the DLL to the app? For example, when I start the thread, I most probably will assign a function (which is inside the EXE) to be the handler for the events (which are triggered from the DLL).

So I guess what I'm asking is - how to load a DLL for continuous work and release it when I'm done - as opposed to the simple method of calling individual functions in the DLL as needed. In the same case - I might assign variables or create objects inside the DLL. How can I assure that once I assign that variable (or create the object), how can I make sure that variable or object will still be available the next time I call the DLL? Obviously it would require a mechanism to Initialize/Finalize the DLL (I.E. create the objects inside the DLL when the DLL is loaded, and free the objects when the DLL is unloaded).

EDIT: In the end, I will wrap the DLL inside of a component, so when an instance of the component is created, DLL will be loaded and a corresponding thread will be created inside the DLL, then when the component is free'd, the DLL is unloaded. Also need to make sure that if there are for example 2 of these components, that there will be 2 instances of the DLL loaded for each component.

Is this in any way related to the use of an IInterface? Because I also have 0 experience with this.

No need to answer it directly with sample source code - a link to a good tutorial would be great.

like image 439
Jerry Dodge Avatar asked Dec 27 '22 10:12

Jerry Dodge


1 Answers

The basic pattern you are looking for goes like this:

  1. EXE calls a function in DLL.
  2. EXE passes parameters as necessary.
  3. DLL performs work, starts thread, returns a handle. And by handle I mean in the loose sense of the work rather than meaning a Windows handle.
  4. EXE can now communicate further with DLL by calling more functions, passing the handle.
  5. DLL can communicate with EXE, e.g. by callbacks, so long as EXE has supplied callbacks.
  6. When it is time to stop, the EXE calls a DLL function, passing the handle. At this point the DLL tidies up.

Behind the handle lies whatever state the DLL needs to keep track of between calls. From the point of view of the EXE this handle is opaque.

This sort of pattern can work just fine even with non-OOP languages like C. However, it's much easier to use OOP facilities. Since you are wishing to cross module boundaries you will be much safer using interfaces rather than Delphi objects. If you pass Delphi objects across module boundaries then you can only pass the data part of the object, but not the code part.

When using interfaces, the interface variable returned by the DLL functions as the handle in my numbered list above. It contains any instance data. Use of interfaces allows for ready extensibility.

As for the threading part, you would do well to use a higher level threading library rather than raw threads. The library I would recommend is Primož Gabrijelčič's OmniThreadLibrary.

Regarding your edit:

I will wrap the DLL inside of a component, so when an instance of the component is created, DLL will be loaded and a corresponding thread will be created inside the DLL, then when the component is free'd, the DLL is unloaded. Also need to make sure that if there are for example 2 of these components, that there will be 2 instances of the DLL loaded for each component.

When you load a DLL into a process there is only ever a single instance of it. In particular if you intend to use global variables, there will be just a single instance of each global variable, not matter how many times you call LoadLibrary.

like image 125
David Heffernan Avatar answered Jan 11 '23 18:01

David Heffernan