I've done About.com guide to embedding dll's in Delphi EXE's which seems to work, so long as I don't actually use the DLL as an external function. Is there anyway to get the code I linked to to work earlier than an unit referenced in the uses clause.
I've tried:
Doing exactly what this code says.
Placing this code in the initialization section of the form that uses the unit that uses the external functions.
Placing this code in the initialization section of the unit that uses the external functions.
And by external functions I'm referring to a function that looks like:
function MyFunction: Integer; stdcall; external 'fundll.dll';
The problem I'm getting is the usual 'fundll.dll' cannot be loaded (because it's not in the directory) . Zarko's code works (pretty sweet, it creates the dll in that folder) when the code gets that far. But it just crashes before the project even gets rolling when I'm using the external functions I need.
You can't do this with external functions - use LoadLibrary() and GetProcAddress() instead after extracting the DLL, and everything should work.
The reason is that any code will be executed only after all entry points have been resolved by the OS loader. Kind of a chicken and egg problem, if you will.
If you are going to use LoadLibrary() and GetProcAddress(), you might prefer to use BTMemoryModule, which would allow you to use the DLL embedded as a resource without saving it to the filesystem (which the user might not be able to do, depending on the machine's security).
http://www.jasontpenny.com/blog/2009/05/01/using-dlls-stored-as-resources-in-delphi-programs/
if you want to call a function in it, you have two choices ...
1) use an exe/dll bundler instead of the resource method.
2) don't link to the library with the external style declaration. instead use LoadLibrary, GetProcAddress, etc to reference the function you need to call.
the resource method and the declaration of the function as external will not mix. windows wants to link your exe to the dll in memory before your code runs to extract the dll.
Related
I would like to write a component with the ability for a developer to either require a DLL or include a unit in their app which compiles the library with the project, without the DLL.
For example, let's say it's called "MyLibrary". If I include MyLibrary in the uses clause, it will by default require that a DLL be distributed with the application. On the other hand, if another unit MyLibraryImplementation is in the uses clause, it will compile everything inside the app without requiring the DLL.
This component is inside a package installed into the IDE.
I'm not even sure the terminology for this, or anything about how to go about this. I'm very familiar with writing DLL's, and not looking for someone to write any full code.
What are the fundamental things I need to know to make this optional DLL possible?
You probably won't find the result very satisfying. Delphi cannot directly load classes from a DLL. Instead, you'll need to define some class in your MyLibrary unit. You'll also have to implement most of the methods there. You're welcome to make those methods be little more than stubs that delegate all the work to functions in the DLL, though. In the stub constructor, call a DLL function that allocates a data structure and returns a handle. In all three other stub methods, pass that handle to the corresponding DLL functions along with the methods' other arguments.
You'll essentially have three parallel implementations of the class:
The one in MyLibrary.pas that's nothing but stubs.
The one in MyLibrary.dll that backs the stubs.
The one in MyLibraryImplementation.pas that does all the same things as the DLL, but internally.
You can probably avoid duplicating too much, but not completely.
You don't need to do any of this, though. For years, Delphi has already offered comparable functionality built in: packages.
If your customers want to have your class's implementation live in a separate module, they can choose the "build with runtime packages" option in their projects' linker settings. Disabling that setting will cause your code to be compiled in to their EXE files instead, and they won't need to distribute the BPL file anymore.
Situation:
a DLL that:
is written and compiled with Delphi XE3 32bit
exports a function that displays a modal VCL-form:
function EditOptions(AIniFileName: PAnsiChar; ALCID: Integer): Boolean; stdcall;
is also a COM-server
an installer created with InnoSetup 5.5.4:
imports said DLL function via external 'EditOptions#files:mydll.dll stdcall'-directive and calls it when needed
explicitly unloads the DLL before registering the COM server via the Inno utility function UnloadDLL
Problem:
When...
Windows is using a theme other than Classic
the modal dialog from the DLL is displayed during installation
the installer hangs upon unloading the DLL
no error messages are shown
logs indicate no runtime exceptions
Please note that to keep this brief, I deliberately left out the explanations for some of the more idiosyncratic details, e.g. why I'm explicitly unloading the DLL or why a COM server needs to have custom exports. Let me know if you think these details would be relevant and should be added.
To further analyse this I created a dummy host EXE that calls the DLL function so I can easier run the whole thing in the debugger. Doing so leads to an AV being raised in TUxThemeStyle.UnloadThemeData on the line that calls CloseThemeData(). When placing a breakpoint directly on that line and stepping forward from the stop, I actually get a "too many consecutive exceptions" error eventually. I can only reproduce the error when I enable runtime themes for the host EXE.
Going back through our git history it appears that this issue exists ever since we switched from Delphi 2010 to XE3 (unfortunately, the installer was not part of our regular test suite so this only cropped up now as work on the actual release comes to a close as the DLL exports exist exclusively for the benefit of the installer).
Any ideas what might be causing this? Could this really be theme-related (I have no custom theme-related code in this project) or is that maybe just a symptom of memory corruption caused somewhere else entirely? E.g. I once had an error that manifested in the form of AVs in the theme tear-down code before but in that case it actually turned out to be caused by the leaking of anonymous method references from initialization sections...
Update: I've worked hard trying to produce a dumbed-down sample project to demonstrate the issue in isolation but so far without luck. I have managed to narrow down a few more things, though. First, here are some more facts about the code:
The dialog I'm showing is a third-degree descendant of TForm. The ancestors accomplish several things:
TAppModalDialog implements a special constructor CreateOnTop that ensures it appears as the topmost window in the current process (the project is a plugin that loads into multi-windowed third-party hosts that do unfortunately not communicate their window handles for use as modal parents) - it accomplishes this by manipulating the global Application.Handle.
TTabbedDialog is part of an interface-based framework that allows registration of "pages" (actually TFrame-descendants) via a factory pattern - at runtime the form will dynamically create TTabSheets in a TPageControl and instantiate and parent the registered page frames to them
I've replaced the call to the actual dialog with a dummy, gradually working myself through the inheritance chain from a blank TForm up to my TAppModalDialog and eventually to my TTabbedDialog class. The problem only starts to occur at that last level. I also commented out all page registrations around the project so that the dialog comes up with an empty page control (this rules out code in any of the pages as the cause for the problem). I then commented out all code and data members in the routines of the TTabbedDialog class itself, leaving only empty method bodies to fulfill the interface implementation requirement and the TPageControl component (along with two empty TImageLists and a TBalloonHint component) -> the error still occurs.
I then copied the call to the dummy dialog into a new DLL project that contains nothing else but this and the tabbed dialog framework. If I load that DLL into my dummy host EXE, the problem does not occur anymore... sigh
So, my suspicion is still that there must be some sort of memory corruption occuring somewhere else entirely and the error I see is only a symptom of that. So the real question is how can I finally get to the bottom of this?
I will now continue by commenting out / removing bits from the production DLL...
I am writing a localization application in which i am reading the DFM information from the application resource through EnumResourceNames API call.
However, the function returns me a name of the form for which the DFM is associated. I tried getting the class from the FindClass, but since this whole operation is coded in a package, the FindClass fails. RegisterClass routine is called from the exe's intialization section.
FindClass works fine when called from within the code written in the exe project. So, i have developed my own registration framework wherein i add all the Form classes, but this is real pain as i need to add the unit of the form and then pass the form class to the RegisterClass routine.
I was hoping if anyone can provide a simple solution of getting all the classes that are in the executable from which the instance of the object can be created by searching the classname.
BTW I am using Delphi 6 Update 2.
Thanks
Rahul W
If the application is calling RegisterClass() and the package is calling FindClass() (or vice versa), that will only work if both the package and the application are compiled with Runtime Packages enabled so they share a single instance of the RTL (which means you have to deploy the RTL and VCL packages alongside your application and package). Otherwise, your application and package will have their own local copies of the RTL instead. In order to share classes in that situation, one project will have to export extra functions that the other project can call when needed to register its local classes in the other project's local class list.
As for detecting the available classes dynamically, that is not possible in D6. The RTTI system did not gain enough detailed information to perform that kind of enumeration until D2010.
I have a Delphi application that I have written a fairly simple wrapper .exe for.
Basically, there was a dll that had a bunch of functions, one of which I would call iteratively once my wrapper did what it needed to. I am not in control of this dll file, and will never be.
Well, now this DLL is a BPL, and I'm not sure how to call functions within that file. Thanks in advance.
The easy way to use functions from a package is to "use" the unit that contains the function, call it as usual, and put the package on the list of your project's runtime packages. For that to work, there are a few requirements:
Your project must use the same Delphi version as was used to compile the package.
You must have access to the DCU file for the unit, or at least the DCP file for the package.
The package must exist in the operating system's search path when your program starts.
If you can't satisfy the third requirement, or if you don't want to have the package loaded all the time, then you can call LoadPackage for it instead. The way to make that work is to have another package that is loaded all the time. It will be used by both your project and the package you wish to load. The intermediate package will expose an interface (such as some registration functions, a variable, or a class) that the main package can use to tell the application what its functions are. You won't be able to "use" the main package's unit in your application directly.
If you can't satisfy the first two requirements, then there is the much harder way, which is also what you'd need to do if your application isn't written in Delphi or C++ Builder. Treat the package like an ordinary DLL. Load it with LoadLibrary. Use GetProcAddress to load its Initialize function, and then call it. (Remember that the calling convention is register, not stdcall.) Then load the address of the function you wish to call, keeping in mind that the name of the function has been mangled to include some unit and type information. Call the Finalize function before you call FreeLibrary. Check the source for LoadPackage and UnloadPackage; whether you need to call CheckForDuplicateUnits probably depends on whether you can satisfy requirement number 1.
A BPL is just a DLL with a few specific additions to it. You should have no trouble calling functions from it just like you did with the DLL, with one specific caveat: The BPL has to be built in the same version of Delphi as you're using. This can be a major drawback if you don't have the source code. If this is a problem for you, you should probably talk with whoever created it and ask them to make it back into a DLL.
A BPL can eliminate a lot of DLL problems. If you can statically link it, the border becomes all but transparent. If you have to load it dynamically, you need one DLL-style access function (usually one that returns an object or an interface) and some common type (interface) definitions. All that should be supplied by the maker of the BPL.
I read this article and find the concept of Virtual Library Interfaces nice for runtime loading of DLLs. However it seems that they aren't available for Win32. Is this true? And if so: Why? I don't see what would tie the idea to .NET.
EDIT: I'm mostly rephrasing here what Rob already wrote. :-)
I'm not after plugins or similar - it's about plain old Win32 DLLs. What appeals to me is the idea to let the compiler deal with all the details of loading a DLL at runtime - no need to call GetProcAddress for every function in the DLL etc.
It seems to me like the three answers so far have completely missed the point of your question. That, or I have. You're asking why Win32 Delphi doesn't have something like the magical Supports function that Hallvard's article talks about, aren't you? Namely, a function that, given the name of a DLL and the type information of an interface, returns an object that implements that interface using the standalone functions exported from the DLL.
Hydra seems to be all about calling .Net code from a Win32 program, not about importing functions from a DLL. TJvPluginManager requires that the plug-in DLLs export a special self-registration function that the manager will call when it loads the DLL, and the function must return an instance of the TJvPlugin class, so the plug-in DLL must be written in Delphi or C++ Builder. The Supports function, on the other hand, works with any DLL written in any language. You could use it on kernel32, if you wanted.
I don't know why Win32 Delphi doesn't have such a thing. Maybe CodeGear didn't see much demand for it since Delphi and Turbo Pascal had already gone for so long without it.
It's certainly possible to write a function that works like that, and I don't expect it would be any harder to write than the .Net version must have been, unless Microsoft's .Net libraries already provide most of the pieces and Delphi just wraps them up into a convenient-to-call function that looks like the several other overloaded versions of Supports that Delphi has had for years.
There would be a few steps to implementing that function in Win32. (I'm providing only a sketch of what's necessary because I don't have a running copy of Delphi handy right now. Ask nicely, and maybe I'll find more details.) First, you'd need to make sure that type information for an interface held, at a minimum, the undecorated names of its methods. Then, Supports would need to generate a function stub for each method in the interface (besides _AddRef, _Release, and QueryInterface). The stub would go something like this, assuming the calling convention is stdcall:
asm
// Pop the return address,
// discard the "this" pointer,
// and restore the return address
pop eax
pop ecx
push eax
jmp AddressOfFunction
end;
As Supports generated each stub, it would fill in the actual function address, gotten from calling GetProcAddress with the name of the corresponding interface method. The stdcall calling convention is easy to wrap like that; cdecl is a little cumbersome; register is a pain in the neck.
Once it has all the stubs generated, it would need to generate an "object" that looks like it implements the given interface. It doesn't have to be an actual class. At compile time, Supports doesn't know the layout of the interface it's going to be asked to implement, so having a class wouldn't accomplish much.
The final step is to provide implementations of the _AddRef, _Release, and QueryInterface. _AddRef would be unremarkable; _Release is where you'd call FreeLibrary when the reference count reached zero; QueryInterface wouldn't do much at all, except claim that it supports IUnknown and the interface given to Supports.
Delphi used to come with a sample program that demonstrated implementing an interface without any classes at all. It was all done with records and function pointers (which is all an interface ultimately is, after all). Delphi also came with the corresponding code to do it with classes, in part to show how much easier Delphi can make things. I can't find the name of the demo program now, but I'm sure it's still around somewhere.
There are a number of Win32 options for this type of functionality. Project JEDI has an open source plugin system as part of the JVCL that loads either DLLs or packages, and can include forms and whatnot as additional functionality.
There are also a number of commercial products available, including the TMS Plugin Framework and RemObjects Hydra.
This is nothing new or special. The article's just talking about plugins. Native code's been able to do plugins for years. The only special thing about P/Invoke is that it allows native code and .NET to talk to each other in a plugin system, and the little trick where "the DLL can be seen as a singleton object that implements the interface [so that] you can use the Supports function from the Borland.Delphi.Win32 unit to check if the DLL and all the methods are available."
If you want to do what the article's talking about in Delphi for Win32, look at the LoadLibrary, GetProcAddress and FreeLibrary Windows API functions. If you absolutely must have an interface like the article describes, you have to write it yourself, either in the DLL (if you wrote the DLL yourself) by writing an exported function that returns an interface, or in the calling app, by writing a function that uses GetProcAddress to create an interface dynamically. (Caution: this requires mucking around with pointers, and is usually more trouble than it's worth.)
Your best bet is probably just to do what Tim Sullivan mentioned: use TJvPluginManager from the JEDI VCL if you only need native code, or Hydra if you have to talk to .NET assemblies.
I've used Hydra myself for a Delphi only solution (i.e., didn't interface to .NET) and it works great for that too. It's easier to use and adds some niceties, but I think that it's basically implemented the same way as the "roll-your-own" plugin framework that is well-described in this article:
http://www.saxon.co.uk/SinglePkg/
I would look for a plugin framework that's interface-based (like Hydra and the "roll-your-own" system in above paragraph), rather than one that simply sends messages between apps.
There is a Delphi plugin framework on sourceforge, don't know whether it's the same one as in JEDI project or not: http://sourceforge.net/projects/rd-dpf
There are also a couple of other commercial solutions, one of which is Dragonsoft's:
http://www.dragonsoft.us/products_dsps.php
What is wrong with doing this with simple com objects? Declare a simple interface that all of your plugins implement, and require that each com object include an exported function that returns its class guid. Then using the "plugins" is as simple as walking thru the plugins directory looking for DLL's which expose the special registration function, invoking it and then using the class guid to then invoke the com object.
I used something like this in a WIN32 commercial application with great success. The advantage was I could switch plugins in and out at will (provided of course the application wasn't running to remove existing ones), the magic was all in the interface that each one implemented.