I have a multithreaded application which dynamically loads dlls (plugins). I have threads in DLL. Between host app and dll is my own SDK which purpose is to enable communication with dll plugins (library interface) and to define shared resources between host app and dlls (data structures, etc..).
Host app is creating a mutex object with WinAPI function CreateMutex and passing a THandle of created mutex to every dll I load. When thread in DLL is changing common resources it uses mutex to protect it. As I said I am using WinAPI.Windows unit for calling CreateMutex and all other mutex related functions (Release etc..).
The idea is to make SDK cross-platform thus I am about to modify SDK and I would like to get rid off unit WinAPI.Windows and all Windows related stuff of course.
I included System.SyncObjs to use TMutex class. Now I am not quite sure how I would let know my dll's about that class. One option is to pass TMutex to my DLL but I think this is not an option if I want to keep primitve data types in my SDK because SDK must be available to other languages such as C++, C#... etc Other idea that crosses my mind is to use named mutexes and just pass a name (string) to DLL.
According to MSDN: If the mutex is a named mutex and the object existed before this function call, the return value is a handle to the existing object, GetLastError returns ERROR_ALREADY_EXISTS, bInitialOwner is ignored, and the calling thread is not granted ownership. However, if the caller has limited access rights, the function will fail with ERROR_ACCESS_DENIED and the caller should use the OpenMutex function.
So I assume DLL will be able to use existing named mutex (MyMutex) when it will call TMutex.Create(...,'MyMutex').
Am I right?
Thank you for your help and your suggestions. I really appreciate it!
Windows mutexes can be "shared" across processes (and even more so in an exe and DLL) - you have two ways:
Use a named mutex. Use the OpenMutex() API to get the handle of an already existing mutex - you need to ensure it's called after CreateMutex() or it won't find the mutex to open.
Use DuplicateHandle() for an unnamed mutex, it returns a new handle valid in the target process (which can be the same, in the case of a DLL)
Often, the API wrapper in Delphi are too limited for "complex" scenarios. Using directly the Windows APIs will give you full access to the underlying functionalities, even if Delphi doesn't expose them. It turn, you will learn more about how Windows works, and it's a knowledge you can always recycle outside Delphi... and you don't need to use ugly hacks to wrap something that doesn't need to get wrapped in interfaces or the like...
If you need cross-platform capabilities, write your own wrappers for the OS mutex implementation - don't rely on the Delphi ones.
Passing a class instance between modules other than runtime packages is not allowed. That is not a valid form of interop.
So I think that the cleanest solution will be to wrap TMutex with an interface. You can pass interfaces between any type of module, even modules compiled by different compilers.
There are a variety of different mutexes available but in my view the obvious choice would be to wrap TMonitor. The interface is simple:
type
IMutex = interface
procedure Acquire; stdcall;
procedure Release; stdcall;
end;
It is perfectly safe to pass this interface between executables and DLLs.
The implementation might be as follows:
type
TXplatMutex = class(TInterfacedObject, IMutex)
public
procedure Acquire; stdcall;
procedure Release; stdcall;
end;
procedure TXplatMutex.Acquire;
begin
TMonitor.Enter(Self);
end;
procedure TXplatMutex.Release;
begin
TMonitor.Exit(Self);
end;
You can wrap any mutex you like in this way. I opted for TMonitor because it is supported on all platforms and is the main tool used by Embarcadero library code for synchronization.
Related
I made a custom control that needs to use API DoDragDrop function and they say I must call OleInitialize before calling this function.
I do that in MyControl.Create method but I get S_FALSE result, so it means that the COM library is already initialized. But who initialize it ?
I do not initialize this before in my application. I am thinking, maybe there is some delphi unit who initialize it in his initialization section... And a secondary question is what should I do, should I continue initializing the COM Library in MyControl.Create method or should I not initialize at all (because it's already initialized) ?
As stated in my answer to a similar question:
In the RTL/VCL source, COM is initialized in the following ways:
By a call to OleInitialize made from Forms.TApplication.Create. So this call will be made for all VCL forms applications, but not, for
example, for service applications.
By a call to CoInitialize or CoInitializeEx in ComObj.InitComObj. This is registered as an InitProc in the
initialization section of the ComObj unit. In turn, the call to
Application.Initialize in your project .dpr file's code will invoke
ComObj.InitComObj.
In many and various other locations around the RTL/VCL. Including, but not limited to, Datasnap, ComServ, Soap, System.Win.Sensors,
Winapi.DirectShow9. Some of these areas of code are more recent than
Delphi 7.
Now, of these various COM initializations, the ones that count are 1
and 2. In any standard VCL forms application, both of these will run
at startup in the main thread. Item 1 runs first and so gets to
initialize COM first. That's the initialization that counts. Item 2
runs after and returns S_FALSE meaning that COM was already
initialized.
All VCL applications include the Forms unit and so you can be sure thaat COM is initialized in the main VCL thread. For other threads you need to initialize COM if necessary.
You must never initialize COM in control or more generally a thread that you are not in control of. If you do so then your initialization may conflict with the apartment type specified by the owner of the thread.
I have written a dll in d-7. It functions correctly. It gets loaded when an application starts and unloaded when it exists.
Now, that dll must also work on the server side of that application, being loaded from the COM+ surrogate (dllhost.exe) as the server is based on com+ technology.
The problem is that one process may have only one handle for loaded library. I cannot have separate handles on each LoadLibrary call.
In com+, one dllhost.exe can serve many clients, which means that if I load an external library it gives the same instance for each clients calls.
So:
1) Is it possible to somehow workaround this problem?
2) Or Is it possible to directly create instance of the class which resides in this dll for each client call?
3) Or How to make a dll thread-safe by instantiating an internal class for each call.
Thanks for suggestions in advance!
Since a DLL uses the local memory of the thread/process that calls it, I'm not sure you're really going to have a "problem". You do not want to have the DLL maintain some global information because that will only lead to threading nightmares.
If you have a function within the DLL return an object reference (effectively a handle) you can also guarantee that each instance gets its own information to play with and not stomp on other processes or threads. Define the function to return your TWhatever object, have the DLL create it ( TWhatever.Create() ) and return it to the calling process. It would then be up to the calling process to free the object. If you need COM+ compatibility then it should be possible to use an interface reference (IWhatever) and return that from your function.
If each thread deals with its own object instance (or interface reference) then you could have the DLL serve as many threads and processes as you wish.
Your question is confusing to me so I'm not sure if I answered it correctly. :p
Delphi.
How from DLL to learn Handle the appendix which has caused this DLL?
That is necessary: Knowing Handle appendices, I wish in Dll to use this Handle at creation of dialogues, because dialogue created as TOpendialog.Create(nil) sometimes it appears under the main window of the basic form. And so, in DLL I would make:
application.handle:=GetExeHandle; // GetExeHandle - How to learn?
Opendialog1:=TOpendialog.Create(application);
...
So it is correct?
The only time your DLL shows a dialog box is when the host application calls a function from your DLL. Include the parent window handle as one of the function's input parameters so that the EXE can tell you which handle to use. Do not attempt to discover the handle yourself. As a library developer, you cannot guess what the host application is doing.
If you don't want to include the handle on every function call, then add an initialization function that users of the DLL need to call before any other functions. Pass the handle in the initialization and then store it in a variable in your DLL so that other functions can use the value when they need it.
Unless you use runtime packages (and you don't, or not the right ones), you are in for a world of pain.
Your library will have its' own copy not only of (T)Application but also of thread sycnhronization queue and event (and everything else).
What you are trying to do can seem to work, but it may (and it will) break anytime cause any complex dialog, regardless if VCL or WinAPI, does its' own message pumping, which will bypass the applications' idle and synchronization handling, resulting in reentrancy issues and random stalls or deadlocks.
You may try to handle a lot of the cases by copying the applications' handles, events etc. to the DLL's globals upon its' initialization (is I tried to do), but (not only) if you use anything like TApplication or TThread in the DLL, it will break sometimes.
You can avoid these problems if you use the right BPL runtime packages in your app and the library, as they will share the same namespace and globals as the application using them.
I am moving some functions to a shared DLL (I want to have some called as a Windows hook).
The actual functions are currently in a unit, and it happens to have some initialization and some finalization code.
I was initially thinking on doing a direct transformation from a unit to a library. So I moved the initialization code in between the main begin and end.. But then I realized I had no place to move the finalization code. I should create and register an special DLL entry point, instead.
My question is. Can I leave the unit with all the functions and the initialization and finalization codes and just create a library stub that uses the unit? will the finalizationit be called?
Code in the initialization sections of the units in the DLL will run when the DLL is first loaded in to the process. The finalization sections fire when the DLL is unloaded from the process.
Eugene is right that you can have more fine-grained control using DLLProc but this is usually only needed for per-thread resources, e.g. thread local storage.
I would point out that there are serious limitations on what can be done during DLLMain which is ultimately where these initialization/finalization sections originate when inside a library. The MSDN documentation basically says that you can do some things, but that there is no list of acceptable behaviour. The closest it comes is to saying that you can call functions in kernel32. Otherwise, all bets are off!
There are lots of articles on the web that describe the issue, but beyond the MSDN topic for DLLMain that I've linked above, I would recommend reading Microsoft's Best Practices for Creating DLLs.
The helpful advice that MSDN offers is that the library can mandate that its users call an initialization function before using the DLL. A corresponding finalization function would be called once you were finished with the DLL. The use of comctl32.dll adopts this idiom, see InitCommonControlsEx.
In my own code I prefer an alternative approach. The initialization sections of all my units register initialization and finalization methods. Then, on the first call to any exported function from my library, the initialization methods are run, in the order in which they were registered. This is not a problem for me to implement because I am already controlling all entry/exit points to my library.
I realise this is more than you asked for, but you may find it helpful to avoid some rather hard to debug problems.
The initialization of a unit will be called if its a program and if its a library.
Same for the finalization.
So yes, you can leave the unit as it is and export the required functionality.
I'd suggest that you implement a DLLMain and handle different situations (process attach, thread attach etc) by calling dedicated procedures/functions for each situation. Then you can call the needed procedures/functions from initialization and finalization, if you need to switch from DLL to unit. The reason is that you might need some fine-grain control when the DLL is attached/detached to/from the thread (which will happen when you set a system-wide hook).
This happend to me as well.
I found out that I had a unit, that initialization section that create a thread or doing some stuff, when the dll is registered.
I have removed this initialization section, and it worked fine.
Since, the initialization is required for .exe application but not for dll application,
there is a variable flag in the system utility, called ModuleIsLib
just do:
initialization
if not ModuleIsLib then
begin
// initialization stuff for .exe file
end;
This can be done also for finalization section as well.
hope it helped..!
On the mainframe using Enterprise Cobol for z/OS, is it possible to dynamically CALL a Cobol Dyamic link library (DLL) program from a cobol program that has been compiled with NODLL?
There are a number of ways to do what you want.
If, by dynamically call, you mean call via a data definition variable, I don't think you can do this with the linker/binder since the binder needs to know the target functions at bind time.
You have to specifically dllload the DLL load module, dllqueryfn the function and call it that way.
To use the linker/binder, I believe the following steps are required (P1 is the NODLL COBOL program doing the calling, P2 is the DLL program being called):
P2 must be compiled and bound with the DLL option.
P1 must be compiled with NODYNAM and bound with DLL.
P1 must contain CALL 'dll-func' (i.e., literal calls only).
When binding P1, SYSLIB must first point to the P2 location.
This will cause the binder to incorporate both P1 and P2 into a single load module which is not exactly DLL calling but I don't think there's any way around that other than the dllload/dllqueryfn solution.
I've used the older-style dll-functions but, if you're at a high-enough level, there are also the newer dlopen/dlsym C helper functions.
This page provides support for my contention that NODLL/DLL programs can only call each other if bound into a single load module. You still have to use static calls however.
This page offers up another option, where you can put the DLL program into the same load module as the calling program and use static calls to get to it. It seems that the DLL program can call other DLL programs not in that load module. So it may be possible to provide a static gateway function in the DLL program that can dynamically call a DLL function not in the load module. This is beyond anything I've ever done on the big iron so you'll have to experiment.
Both those pages are from the publib-boulder sites which everyone using an IBM product should know about (along with the redbooks/redpapers site as well).
Me, I prefer the dllload/dllqueryfn solution since that's what I'm used to from AIX and other UNIXes and it seems to provide maximum flexibility.