

A.M. Hoornweg
Members-
Content Count
507 -
Joined
-
Last visited
-
Days Won
9
Everything posted by A.M. Hoornweg
-
Hello all, All of a sudden I can't login to Quality Central ( https://quality.embarcadero.com/secure/Dashboard.jspa ) anymore. And the "contact support" link on that page requires me to be logged in, so that effectively makes support totally unreachable to me. Can anyone please give me a pointer to the person or team who is responsible for that web site?
-
FastMM - Fragmentation Analysis?
A.M. Hoornweg replied to Lars Fosdal's topic in RTL and Delphi Object Pascal
You could use OutputDebugString in conjunction with Sysinternals' DebugView to monitor the size of your lists in certain time intervals. That way you can observe if one of your lists is growing out of control. DebugView can do tcpip client/server by the way, that way you can observe the debugging output on a different computer. -
FastMM - Fragmentation Analysis?
A.M. Hoornweg replied to Lars Fosdal's topic in RTL and Delphi Object Pascal
Maybe you should look at allocations that bypass Delphi's memory manager and hence not get caught by FastMM4. I mean stuff like VirtualAlloc, GlobalAlloc, LocalAlloc and HeapAlloc. Are you using any external DLLs written in C ?. You max need a tool like AQTime or Deleaker to track down such leaks. -
Why should I use good source control versioning system?
A.M. Hoornweg replied to Mike Torrettinni's topic in Tips / Blogs / Tutorials / Videos
Same here. In the hands of a more capable company, Delphi could/would have conquered the world. Out of interest, which development system would you pick today? -
Why should I use good source control versioning system?
A.M. Hoornweg replied to Mike Torrettinni's topic in Tips / Blogs / Tutorials / Videos
YES you need it. With a source control system you can make as many backups (commits) per day as you want and you can return to any older version of a file if you broke something. A few tips: - There are very good freeware GUIs available (such as TortoiseSVN and TortoiseGit). Please use those, they save a lot of hassle. - I personally don't let the Delphi IDE manage the files in the repository, I prefer to do it manually. I use both svn and git, but I use them exclusively using the aforementioned tools. - It isn't really necessary to use an external server for your own (non-shared) repositories. An external USB drive will do just fine. - Whenever you want to add/delete/move/rename a file in your working copy, don't do it with the Windows explorer, only do it with Tortoise. -
Hello all, does anyone have any links to documentation/examples about the correct use of tContainedObject and tAggregatedObject? I find the little documentation I can find rather confusing. Kind regards, Arthur
-
Okay, that makes sense; so if I use tAggregatedObject then I can use the "AS" keyword to freely switch between the inner and the outer interface (see example 1) whereas in tContainedObject that isn't possible (it would only let me switch from the outer to the inner interface, right?) .
-
In my experience, when reporting is done on oil wells in the Middle East, the Arabic text is often interspersed with English technical terms. And for a developer it is quite a challenge to get mixed LTR-RTL text input right.
-
But tAggregatedObject doesn't DO the reference counting, it lets the controller (the owner) do that. And the controller explicitly manages the inner object's lifetime, not through reference counting. function TAggregatedObject._AddRef: Integer; begin Result := FController._AddRef; end; And when using a plain vanilla tObject (my examples 2 and 3), the owner ALSO does the reference counting. Same thing, but faster (since the _addref isn't chained). So I still don't see what tAggregatedObject is actually meant for, what problem it is supposed to solve!
-
COM is not the problem, I've been implementing COM objects for years. My question is really specific about the correct use and usefulness of tAggregatedObject and tContainedObject, because as far as I can see they are not needed at all to build aggregates, tInterfacedobject can already do so using ordinary tObjects. So I'm probably missing something essential about their use and usefulness! For example, this aggregate uses a tAggregatedObject: type iHello = interface ['{58AD07B9-FCE5-494A-94B2-E1CAF7D05B1D}'] procedure Hello; end; iGoodbye = interface ['{35079C32-AF3D-4E9D-808C-6A6DDED38663}'] procedure Goodbye; end; tAggregate = class(taggregatedobject, iHello) procedure Hello; end; tCompositeObject1 = class(tinterfacedobject, iHello, iGoodbye) protected ainner: tAggregate; function GetInner: iHello; public procedure Goodbye; destructor Destroy; override; property Inner: iHello read GetInner implements iHello; end; procedure tAggregate.Hello; begin messagebox(0, pchar('Hello'), pchar('Hello'), mb_ok); end; destructor tCompositeObject1.Destroy; begin messagebox(0, pchar('Destructor'), pchar('tCompositeObject1'), mb_ok); ainner.free; inherited; end; function tCompositeObject1.GetInner: iHello; begin if not assigned(ainner) then ainner := tAggregate.create(self); result := ainner; end; procedure tCompositeObject1.Goodbye; begin messagebox(0, pchar('Goodbye'), pchar('Goodbye'), mb_ok); end; procedure TestCode1; var Hello: iHello; Goodbye: iGoodbye; begin Goodbye := tCompositeObject1.create; Goodbye.Goodbye; Hello := Goodbye as iHello; Hello.Hello; end; ... and this one does the very same thing using a plain vanilla tObject: type iHello = interface ['{58AD07B9-FCE5-494A-94B2-E1CAF7D05B1D}'] procedure Hello; end; iGoodbye = interface ['{35079C32-AF3D-4E9D-808C-6A6DDED38663}'] procedure Goodbye; end; tSimpleObject = class procedure Hello; end; tCompositeObject2 = class(tinterfacedobject, iHello, iGoodbye) protected ainner: tSimpleObject; function GetInner: tSimpleObject; public procedure Goodbye; destructor Destroy; override; property Inner: tSimpleObject read GetInner implements iHello; end; procedure tSimpleObject.Hello; begin messagebox(0, pchar('Hello'), pchar('Hello'), mb_ok); end; destructor tCompositeObject2.Destroy; begin messagebox(0, pchar('Destructor'), pchar('tCompositeObject2'), mb_ok); ainner.free; inherited; end; function tCompositeObject2.GetInner: tSimpleObject; begin if not assigned(ainner) then ainner := tSimpleObject.create; result := ainner; end; procedure tCompositeObject2.Goodbye; begin messagebox(0, pchar('Goodbye'), pchar('Goodbye'), mb_ok); end; procedure TestCode2; var Hello: iHello; Goodbye: iGoodbye; begin Hello := tCompositeObject2.create; Hello.Hello; Goodbye := Hello as iGoodbye; Goodbye.Goodbye; end So is there any advantage in using tAggregatedObject / tcontainedobject at all ? I currently see more advantages in using tObject, because that allows me to take an existing class and encapsulate it inside a wrapper class whenever I want it to be interface based. For example, these few lines of code make a tStringlist interface-based, expose the methods add, get and put and make the whole thing reference counted: type // Just expose a selected bunch of methods of tStrings iStrings = interface ['{242798EB-0A53-4284-BA16-306FF354E2AC}'] function Add(const S: string): Integer; function Get(Index: Integer): string; procedure Put(Index: Integer; const S: string); property Strings[index: Integer]: string read Get write Put; default; end; tInterfacedStrings = class(tinterfacedobject, iStrings) protected fList: tStringlist; function getList: tStringlist; public destructor Destroy; override; property list: tStringlist read getList implements iStrings; end; destructor tInterfacedStrings.Destroy; begin fList.free; inherited; end; function tInterfacedStrings.getList: tStringlist; begin if not assigned(fList) then fList := tStringlist.create; result := fList; end;
-
Hello all, when I deploy a FMX application to Ubuntu (in this case the "Screenshot" fmx demo) the Delphi 10.4 debugger hangs totally. My Windows and Linux machines are both VMWare VM's. I can see that the freshly compiled executable appears in the home/PAServer/scratch-dir/myname/Screenshot directory. The message log in the Delphi IDE gives a warning "Local file \Redist\libfmux.so not found. Skipping deployment." The executable is not started on the Linux system by PAServer. I am able to start the executable manually, so the executable itself must be OK. But Delphi hangs so thoroughly that I can't debug it. I can only terminate Delphi in the task manager. Am I doing something wrong?
-
Sydney, debugger not working on Ubuntu LTS 20.04
A.M. Hoornweg replied to A.M. Hoornweg's topic in Cross-platform
I have re-installed Delphi 10.4 after thoroughly cleaning my hard drive and registry from older Delphi 10.x leftovers and now it works. -
Hello all, I'm totally new to Android, and so far I'm having zero success getting Embarcadero's sample programs to run on Android. I am running Delphi 10.4 inside a VMWare VM. On my host machine, I have the Bluestacks 4.215.0.1019 emulator running, with ADB debugging enabled. Connection details: I am aware that Bluestacks only binds to localhost (127.0.0.1) so I have setup a port forwarding on the host (netsh interface portproxy add v4tov4 listenport=5556 connectaddress=127.0.0.1 connectport=5555) so that I can connect to the emulator from external IP addresses through TCP port 5556. I have enabled both ports 5555 and 5556 in the firewall. I have tested this setup and I can successfully connect to the emulator from my Delphi VM ("adb connect ip-address:5556") and send adb commands to it. I had expected this connectivity to be the biggest hurdle but it worked immediately. I have cloned Embarcadero's official sample repository from github (https://github.com/Embarcadero/RADStudio10.4Demos.git) and now I'm trying to compile and run the application in "Samples\Object Pascal\Multi-Device Samples\User Interface\Forms". I've activated the Android 32-bit target (guessing that Bluestacks emulates a 32 bit device) and the Delphi IDE "sees" the device without problems (see screenshot), it's called "SM-G973F". Since this is an "official" demo application, I was hoping things would work out of the box so I could use it as a starting point! But when I press F9, Delphi does a lengthy compiling act, and then throws the following errors: [PAClient Error] Error: E2312 Unable to execute '"C:\Users\Public\Documents\Embarcadero\Studio\21.0\PlatformSDKs\android-sdk-windows\build-tools\28.0.2\Aapt.exe" package -f -M "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\AndroidManifest.xml" -F "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\bin\Forms-unsigned.apk" -I "C:\Users\Public\Documents\Embarcadero\Studio\21.0\PlatformSDKs\android-sdk-windows\platforms\android-26\android.jar" -S "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\res" -A "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\assets" "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\library" "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\classes"' (Error 1) [PAClient Error] Error: E2312 C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\AndroidManifest.xml:21: error: No resource identifier found for attribute 'requestLegacyExternalStorage' in package 'android' The error messages aren't helpful at all, what the heck is "Error 1" supposed to mean? Can anyone point me to a solution? Thanks in advance, Arthur
-
Cannot run sample programs on Android
A.M. Hoornweg replied to A.M. Hoornweg's topic in Cross-platform
It wouldn't work. I have de-installed Delphi Sydney and deleted all Embarcadero folders and registry keys plus everything that had to do with Java and Android. Then I re-installed Delphi and now the compiler deploys the executable as expected. The executable won't start on Bluestacks 4 (screen stays black), however, so I'll try a hardware device next. -
Cannot run sample programs on Android
A.M. Hoornweg replied to A.M. Hoornweg's topic in Cross-platform
I would be totally grateful if you'd tell me how to do that! I'm an absolute beginner with Android. -
Cannot run sample programs on Android
A.M. Hoornweg replied to A.M. Hoornweg's topic in Cross-platform
Deleting the xml file makes no difference. It gets re-created, yes, and then I get the exact same error messages as before. And then Delphi hangs completely, I have to shoot it down in the task manager. All in all, deploying to Android seems unfunctional. -
After installing "Rad Studio 10.4 Patch (Patch Tool) Test 1.0" which recently appeared in GetIt package manager, DUnitX has disappeared from my system. How do I get it back?
-
Hello all, does anyone know if Delphi 10.4 can co-exist peacefully with 10.3 Rio on the same system without one breaking the other, and can I un-install Rio later without damaging the Sydney installation? Especially if one intends to do some multi-platform (Android/Linux) work?
-
Thank you all! So I'll backup my VM, enlarge the C partition and install Sydney. At a later point in time I'll uninstall Rio to free up space.
-
App tethering? http://docwiki.embarcadero.com/RADStudio/Rio/en/Sharing_Data_with_Remote_Applications_Using_App_Tethering
-
It happens to me about 3 times a day that when I press F9 in Delphi Rio that the IDE reports "Disconnected Session" and then just hangs. I have to kill it using the task manager. It is very irritating, what can be the cause of this?
-
I wonder about sendmessage being executed in the context of the calling thread. Is that documented somewhere? The HWnd could be in an entirely different process, so there must be some kind of marshaling in between.
-
How do you deal with deprecated symbols in backwards compatible code?
A.M. Hoornweg replied to dummzeuch's topic in RTL and Delphi Object Pascal
I also usually use class helpers, that implement the new methods for the old Delphi versions. Not the other way around! -
The interfaces in Delphi are bad?
A.M. Hoornweg replied to Jacek Laskowski's topic in RTL and Delphi Object Pascal
You shouldn't, because the component's owner manages its lifetime. Refcounted objects do not have an owner, they manage their own lifetime. Freeing an object twice is a really bad idea. -
The interfaces in Delphi are bad?
A.M. Hoornweg replied to Jacek Laskowski's topic in RTL and Delphi Object Pascal
I use interfaces all the time, and there are simple ways to make existing classes support interfaces with or without reference counting, without having to derive from a common base class like tInterfacedObject. If I want to modify any class in such a way that it supports interfaces without reference counting, I simply add dummy methods _AddRef, _Release, and QueryInterface: Type tNewObject = class(TOldObject, IInterface) protected // IInterface function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end; function tNewObject._AddRef: Integer; begin Result := -1; end; function tNewObject._Release: Integer; begin Result := -1; end; function tNewObject.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := S_OK else Result := E_NOINTERFACE; end; And similarly, it is possible to make any existing class support interfaces with reference counting, it just takes a few more methods: TNewObject = class(TOldObject, IInterface) protected FRefCount: Integer; function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; public procedure AfterConstruction; override; procedure BeforeDestruction; override; class function NewInstance: TObject; override; property RefCount: Integer read FRefCount; end; procedure TNewObject.AfterConstruction; begin // Release the constructor's implicit refcount InterlockedDecrement(FRefCount); Inherited; end; procedure TNewObject.BeforeDestruction; begin if RefCount <> 0 then Error(reInvalidPtr); Inherited; end; // Set an implicit refcount so that refcounting // during construction won't destroy the object. class function TNewObject.NewInstance: TObject; begin Result := inherited NewInstance; TNewObject(Result).FRefCount := 1; end; function TNewObject.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end; function TNewObject._AddRef: Integer; begin Result := InterlockedIncrement(FRefCount); end; function TNewObject._Release: Integer; begin Result := InterlockedDecrement(FRefCount); if Result = 0 then Destroy; end;