I am using Delphi XE. I have come across a memory leak problem using Delphi Soap. It turns out to be due to a missing .Free call in TWSDLLookup.Destroy, as described in QC 91160
The problem that I have is the described work-around, which is simply to add FLookup.Free to the TWSDLLookup.Destroy method.
I don't want to change the Delphi source, so I tried copying the unit to my project folder, making the change and recompiling, as described here in Tom's answer. The problem with this technique is that it apparently only works if you also recompile all the dependent units. I have tried copying just WSDLLookup.pas to my project directory and I get a Stackoverflow error. I'm not familiar with Web Services / SOAP so I don't know what other units I should copy over if I do use this technique.
Rob Kennedy's answer on the same page describes a different technique involving code hooking - but it doesn't seem to apply to object methods. I have done as he suggests and downloaded the free code for the TNT Unicode controls and located the relevant procedures, but I have been unable to find info on how to hook an object's methods - if indeed this is possible. If I could do this, I would then hook TWSDLLookup.Destroy and add the FLookup.Free call.
Any ideas for how to fix this will be much appreciated. I'm a bit of a newbie programmer so I'm hoping that I've missed something obvious?
What you are trying to do does in fact work fine. I tested it out myself. Here's the project file I used:
program WSDLLookupTest;
{$APPTYPE CONSOLE}
uses
WSDLLookup in 'WSDLLookup.pas';
var
intf: IInterface;
begin
intf := GetWSDLLookup as IInterface;
end.
I made a copy of the WSDLLookup.pas file and placed it in the same directory as the .dpr file. Then, in the copy rather than the original, I modified TWSDLLookup.Destroy.
destructor TWSDLLookup.Destroy;
begin
Beep;
ClearWSDLLookup;
FLookup.Free;
inherited;
end;
I added the Beep to prove to myself that this code was indeed being executed.
In your position I would definitely use this solution instead of attempting code hooks. And of course the other simple solution is to upgrade to a later Delphi version.
One thing to be careful of is to remember to remove the modified unit when you do upgrade. The leak was fixed in XE2.
Related
Okay, so this is not the best practice situation, but luckily I have an answer, so please bear with me.
I'm working on a rather large Delphi project with lots of external APIs used. Those APIs are plugged in different ways, including units wrapped into IFDEFs in the DPR itself, when they are platform-dependent. Having IFDEFs in DPR is a bad practice - sure, but it is handy to have all the units listed in the project tree to switch between them (rather than switch between projects).
So I was adding another alternative API implementation to the project and as usual - wrapped the existing solution units into the {$IFDEF SOME_API_DLL} clause and a new solution units into another {$IFDEF SOME_API_EXE}.
Anyways, I noticed soon after, that the IDE started to freeze semi-randomly after just 3-5min of coding, which is unbearable toll.. The IDE would hog one CPU (e.g. 13% on 8-core PC). I was able to isolate the cause to be invocation of "autocomplete", "code completion" (Ctrl+Space) and "jump to declaration (Ctrl+Click).
The main question is - what could cause the IDE to freeze on how to resolve this?
I'm using Delphi XE8, but switching to other versions didn't help. Unfortunately newer 10.3+ versions (with claimed rewritten Code Insight) could not be tested/used due to third-party components.
Thanks to the bug being well connected to the new API implementation, I was able to track down the cause. So it appears that IDE does not like DPR files with IFDEFs (old news), but the real bummer seems to be that IDE handles IFDEFs okay only if they wrap only one unit.
The hint to the solution was the Project Tree, which gets auto-updated with units in DPR, but it auto-included only the first units after the IFDEF. Apparently, thats what also throws off the track the auto-completion.
Bad DPR structure that causes IDE to freeze on code-completion:
{$IFDEF EXTAI_API_DLL}
KM_ExtAI_DLL in 'src\KM_ExtAI_DLL.pas',
KM_ExtAI_DLLs in 'src\KM_ExtAI_DLLs.pas',
KM_ExtAI_SharedTypes in 'src\KM_ExtAI_SharedTypes.pas',
KM_ExtAI_SharedInterfaces in 'src\KM_ExtAI_SharedInterfaces.pas',
KM_ExtAIActions in 'src\KM_ExtAIActions.pas',
KM_ExtAIMaster in 'src\KM_ExtAIMaster.pas',
KM_ExtAIStates in 'src\KM_ExtAIStates.pas',
KM_ExtAIUtils in 'src\KM_ExtAIUtils.pas',
{$ENDIF}
Good DPR structure that lets IDE work well:
{$IFDEF EXTAI_API_DLL}KM_ExtAI_DLL in 'src\KM_ExtAI_DLL.pas',{$ENDIF}
{$IFDEF EXTAI_API_DLL}KM_ExtAI_DLLs in 'src\KM_ExtAI_DLLs.pas',{$ENDIF}
{$IFDEF EXTAI_API_DLL}KM_ExtAI_SharedTypes in 'src\KM_ExtAI_SharedTypes.pas',{$ENDIF}
{$IFDEF EXTAI_API_DLL}KM_ExtAI_SharedInterfaces in 'src\KM_ExtAI_SharedInterfaces.pas',{$ENDIF}
{$IFDEF EXTAI_API_DLL}KM_ExtAIActions in 'src\KM_ExtAIActions.pas',{$ENDIF}
{$IFDEF EXTAI_API_DLL}KM_ExtAIMaster in 'src\KM_ExtAIMaster.pas',{$ENDIF}
{$IFDEF EXTAI_API_DLL}KM_ExtAIStates in 'src\KM_ExtAIStates.pas',{$ENDIF}
{$IFDEF EXTAI_API_DLL}KM_ExtAIUtils in 'src\KM_ExtAIUtils.pas',{$ENDIF}
I need to open a webpage with safari in my iOS application.
With XE2 there was iphoneall unit, which exposed UIApplication. XE4 doesn't use FPC anymore, so I can't use that.
Embarcadero documentation
says I can use SDKs only with C++ or using delphi interfaces (and still, macapi is for OSX only, not iOS). So, it seems that there is no interface for UIKit framework?!
Another solution I tried was:
_system('open http://www.google.com');
But that had no affect at all!
Is there any other ways to open urls or am I out of luck to accomplish it?
I know there is TWebBrowser component for ios, but I wouldn't want to take that road just to display a webpage.
By chance, someone at Embarcadero posted a code snippet to do exactly this two days ago.
If you are using XE4, look in the Samples, and you can find one (sorry, not sure of the name) where the final code is:
OpenURL('http://www.embarcadero.com');
This uses the XE4 FireMonkey framework and a class helper written by David Clegg, available in the sample.
If you are using an older version of FireMonkey, you can use the rather more cumbersome code:
function SharedApplication: UIApplication;
begin
Result := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication);
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
SharedApplication.openURL(TNSURL.Wrap(TNSURL.OCClass.URLWithString(NSSTR(PChar(String('http://www.embarcadero.com'))))));
end;
(Attribution: Code snippets all copied from the linked blog post.)
There is also a very old forum post from the early days of FireMonkey showing how to tackle these problems in general (basically, string <-> NSString <-> NSURL), and while it's a bit out of date - as you can see by the above code, FireMonkey has matured greatly - it may give some insight into the underlying reason for the code.
maybe this is a lame question, but nevertheless...
I asked some questions about the plugins in delphi. What is the better way dll, bpl, OCX, scripting engine...
I dont feel like to distribute all *.bpls, and all its dependencies...
All I need is a *.dll which contains a TForm. And that Form should be placed into the host application.
There is no direct support for this in delphi (very sad situation). Some workarounds exists, but there are problems with tab key etc... So non workaround is perfect.
But maybe there is an another possibility. Inject dll code directly into the host *.exe.
So the *.exe will think that injected code his its own... And lot of problems (e.g. with tab key in form) should be gone.
Is it possible? isn't it a dirty hack, e.g. is that technique "programatically" legal?
(I have no experience with code injecting, and maybe it doesn't make sence what I'm saying here ;)
best regards
Peter
[edited]
To clarify some things... When we put a TForm in dll and than we try this form embed to the host *.exe application, a lot of problems arise. First is an error "cannot assign TFont to a TFont", but there is a some workaround for this.
Second is that host application take whole embeded form as one component, so you cannot use a tab key. (After pressing tab, focus will completly jump out of embeded form). Also we have some workaround for this, but it is far away from perfect...
So I had an idea, if we inject some code to the host, maybe host will be think that emebeded form his is own code, so tab key will be working.
But as I said before, I dont know anything about injecting, just a (maybe) crazy idea ;)
This is perfectly possible without recourse to any of the hacks you describe. For example:
library FormDLL;
uses
Windows,
Forms,
uMyForm in 'uMyForm.pas' {MyForm};
procedure ShowForm(MainFormHandle: HWND); stdcall;
begin
Application.Handle := MainFormHandle;
with TMyForm.Create(nil) do begin
ShowModal;
Free;
end;
end;
exports
ShowForm;
begin
end.
You can put pretty much anything you like in TMyForm. On the other side create a Delphi app and add the following code to call the DLL:
procedure ShowForm(MainFormHandle: HWND); stdcall; external 'FormDLL.dll';
procedure TMainForm.Button1Click(Sender: TObject);
begin
ShowForm(Handle);
end;
This behaves just perfectly.
So, I'm afraid it's not obvious what your problem is. If you can supply more details, then please do so.
I have a class in a unit. Usually, when I changed the algorithm of its methods, I have to recompile it and deliver the patch as a whole.
I think to create the instance of the class using DLL. After searching in delphi.about.com, I found that instead of using DLL, I can use BPL. It is a DLL for Delphi. The problem is almost all examples I found is only telling how to export a function.
I want to dynamically load the BPL, and whenever I replace the BPL, I can get the latest algorithm of the class, not only the functions I export.
Article I have read:
- http://delphi.about.com/od/objectpascalide/a/bpl_vs_dll.htm
- Plugins system for Delphi application - bpl vs dll?
- http://delphi.about.com/library/weekly/aa012301a.htm
Any URL or SAMPLE how to create a BPL from scratch to encapsulate a component or a class is greatly appreciated.
Dear Guru,
Suppose I have code like this:
unit unitA;
interface
type
B = class(TObject)
public
procedure HelloB;
end;
A = class(TObject)
public
function GetB: B;
function HelloA: String;
procedure Help;
end;
implementation
uses
Dialogs;
{ B }
procedure B.HelloB;
begin
ShowMessage('B');
end;
{ A }
function A.GetB: B;
begin
Result := B.Create;
end;
function A.HelloA: String;
begin
Result := 'Hello, this is A';
end;
procedure A.Help;
begin
//do something
end;
end.
I want to export all public methods of A. How to make it a DLL?
How to use it from another unit where to import it?
let's say:
var a: A;
a := A.Create;
a.GetB;
showMessage(a.HelloA);
A is not declared in the unit (it is in the DLL).
Please advise.
Hurray. I got it last night. All I have to do is make the object implement an interface which is used in the caller unit to catch the instance of object returned by the DLL.
Thank you all.
Mason nailed it already, but let me elaborate on why BPLs aren't what you are looking for.
BPLs are a means for the Delphi IDE to load components that share the same memory manager and RTL. (Type identity works almost transparently using BPLs)
However, the dependencies you are getting tied up in are almost always unacceptable. Except for the IDE, which cannot handle different versions of RTL and VCL anyway.
When you pass only interface references between your application and its DLLs, then you don't have to share RTL, VCL or shared packages at all.
It also means that you could write some DLLs in another language (C++, C#, FPC, another Delphi version), and still use objects. Which can be tempting when you don't want to port your main app but still want to use existing libraries that are not available for Delphi, or your version of Delphi.
The problem with putting a class in an external file is that your main application needs to know some way to refer to it. It will either have to descend from a base class that exposes all the methods you need as virtual methods, or implement an interface that contains all the functionality you need from it.
If you already know what the interface of the object should look like, and all you're changing is implementation details such as internal algorithms, probably the easiest thing would be to make your class implement an interface and put it in a DLL that exports a function that returns an instance of this interface. That way you don't need to worry about breaking your app up into packages, which can be a real hassle.
I see nothing in your problem description suggesting you would need to explicitly export anything from the package or that you would need to load it dynamically at run time. Instead, it's enough that your functions reside in a run-time package that can be replaced separately from the main program.
Start a new package project and move your class's unit into that project along with any other units it depends on. Compile the project. If the compiler warns about "implicitly including" any other units, add those to the package, too.
Now, remove any of the package units from the EXE project. There should be no units that are members of both projects. Next, turn on the "build with run-time packages" checkbox in your EXE's project options. Add your package to the semicolon-separated list of package names. The RTL and VCL packages will probably also be on that list.
Compile both projects, and you're done.
If you make changes to your class implementation, you can recompile the package only and send a new version to customers. The program will automatically get the new changes when you replace the original file with the new one. The package is listed in the program's import table, so the OS will automatically load the BPL file when it loads the EXE. The EXE doesn't need to run any special code to load the package.
Delphi can create DLL to export functions or BPL to export component.
You can create component, compile it (use the same compiler settings as in your main app), and Delphi will create .bpl. Then import this component to Delphi and compile your app with this compomponent as a package.
My experience with components created with Delphi 4 proved that one, big application is more reliable than application with separate .bpls. It was multithreaded server and it worked fine if compiled standalone, while crashed after short time if compiled with packages. I hope newer versions of Delphi improved in this area.
Be aware of memory management (in app do not free memeory allocated in package and vice versa) and compiler settings.
If you like about.com then this link will be useful: Introduction to Packages; BPLs are special DLLs!
BPLs have their usage. For example if you have to make a very huge application like an Erp, you need to try to use BPLs seriously.
In the other hand, BPLs aren't responsible of crashing applications. Bad usage of BPLs does it.
you can try the MAF Components, they handle plugins and much more for you without extra code. Comes with tutorials and a demo application with source.
http://www.maf-components.com
Has anyone come across a framework or library for Delphi to simplify the generation of x86 code? I am not looking for an assembler, but rather a framework that abstracts the code generation process above the low level bits and bytes. Ideally I would like to build on top of an existing library or framework rather than hardcode the logic on a case by case basis.
The initial usage will be to generate small code stubs at runtime similar to the way Delphi dispatches SOAP requests. If I cannot find something I will likely roll my own, but I would hate to reinvent the wheel. Something in "C" might me interesting provided the license will permit translation and use in commercial and open source projects.
Update:
Here is some more context: What I am working toward is runtime implementation of interfaces and/or classes as part of a persistence framework. Something sort of like Java annotation driven persistence (JPA/EJB3) except with a distinctly Delphi flavor. The invocation target is a modular/extensible framework which will implement a generalized persistence model. I need to dispatch and hook method calls based on RTTI and an annotation/attribute model (something similar to InstantObjects metadata) in a very dynamic and fluid manner.
Thanks,
David
The more I have thought about your question. I am not sure if all you trying to just do Dynamic Method Invocation. Even though your asking about generating x86 code.
There are several techiniques that do this.
If you know the signature of the method in question you can do it easily by using a
TMethod and setting the method address and data.
procedure TForm8.Button1Click(Sender: TObject);
begin
Showmessage('Hello1');
end;
procedure TForm8.Button2Click(Sender: TObject);
var
M : TMethod;
begin
M.Code := MethodAddress('Button1Click');
M.Data := Self;
TNotifyEvent(M)(self);
end;
If you don't know the method signature you can write the class with {$METHODINFO ON}
Then use the functionality in ObjAuto.pas to invoke the method.
I have an example in my RTTI Presentation code from DelphiLive on how to do that.
According to features of PaxCompiler, you can create stand alone executable files.
Very spectulative answer:
Something like LLVM? I am not sure if it can be used from delphi or not, but you should be able to create dll's wth it.
Logically you would simply generate delphi code, compile to a DLL/BPL by cmdline compiler and then dyn load that one?
Unfortunately Delphi Explorer doesn't come with the cmdline compiler though. And your main binary would also have to be in Delphi Explorer (or at least in D2006 if that is binary compatible enough)
Any mix of Delphi versions (or Free Pascal) will probably not work on the package or HLL level, only at basic procedural DLL level.
I just found an interesting framework that does much of what I was looking for when I originally posted the question. A little late for my purposes, but thought someone else might find this useful:
DAsmJit a Delphi port of the asmjit project