-
Content Count
3060 -
Joined
-
Last visited
-
Days Won
139
Everything posted by Remy Lebeau
-
Indy does not use SVN anymore. The latest code is now on GitHub. That should be fine, though the resulting BPLs won't be named consistently with other packages installed in 10.3. I just haven't gotten around to making and posting project files for 260 yet. In part because I don't have 10.3 installed! Hmm, interesting. I was not aware of that. I'll have to consider disabling that warning. IfIndex is used when Indy calls GetAdaptersAddresses(), and the IP_ADAPTER_ADDRESSES record has an IfIndex field defined, so not sure why that error would be happening. AdapterIndex is used when Indy calls GetAdaptersInfo(), but the IP_ADAPTER_INFO record does not have an AdapterIndex field defined. Not sure where I got that idea from when I wrote that code. I have fixed that now.
-
Android Mobile application using Firemonkey
Remy Lebeau replied to Antony Augustus's topic in I made this
In VCL, colors are expressed using TColor. You can use the RGB() function or the TColorRec record to specify decimal/hex values for the individual R, G, and B channels. In FMX, colors are expressed using TAlphaColor. You can use the TAlphaColorRec record to specify decimal/hex values for the individual R, G, B, and A channels.- 18 replies
-
- android
- firemonkey
-
(and 1 more)
Tagged with:
-
Tool to fix up uses clause unit namespaces?
Remy Lebeau replied to Vincent Parrett's topic in General Help
Do you really need this, though? If you simply include 'System' and 'Vcl' in the Unit Scope Names list in your project options, you won't need to update the 'uses' clauses at all. -
Then do what Dave said to do: In other words, add something like this to the code: procedure TPhoneDialerForm.FormCreate(Sender: TObject); begin {$IFDEF ANDROID} FCallPhonePermission := JStringToString(TJManifest_permission.JavaClass.CALL_PHONE); {$ENDIF} { test whether the PhoneDialer services are supported } if TPlatformServices.Current.SupportsPlatformService(IFMXPhoneDialerService, FPhoneDialerService) then FPhoneDialerService.OnCallStateChanged := CallStateChanged; // <-- ADD THIS! end; procedure TPhoneDialerForm.CallStateChanged(const ACallID: String; const AState: TCallState); var Calls: TCalls; Call: TCall; begin if AState = TCallState.Incoming then begin Calls := FPhoneDialerService.GetCurrentCalls; try for Call in Calls do begin if Call.GetCallID = ACallID then begin // use Call as needed ... Exit; end; end; finally for Call in Calls do Call.Free; end; end; end;
-
New MemManager allocator Win,Osx,Ios,Android,Linux?
Remy Lebeau replied to RDP1974's topic in RTL and Delphi Object Pascal
And how are you going to handle the case where a thread allocates some memory, then that thread terminates/dies and its ThreadID gets reused by a new thread, and then that new thread wants to deallocate the earlier memory? Storing the ThreadID in the memory metadata may not suffice, and if you use TLS storage for the memory then you lose the original memory altogether. Even if the SAME thread does the allocating and deallocating, you still need some kind of thread-safe mechanism to synchronize (de)allocations with OTHER threads so they don't try to reuse/trample the same memory block while it is still being used. -
How do we know if the, TCP Socket connection is connected
Remy Lebeau replied to Turan Can's topic in Cross-platform
What makes you think it is any different for Android? Most platforms use the same Berkeley-based socket API. That is true for Windows. That is true for Posix systems, like Linux (which Android runs on top of). select(), recv(), these functions exist and behave the same on Android (when coding at the native layer, as you describe) as they do on Windows. -
Yes. Indy 11 will just be a maintenance cleanup, no real new functionality (anything that does get added will likely be able to backport to Indy 10), so old projects won't have to worry about Indy 11. But Indy 12 will likely start making big changes and adding new features, and it likely won't make sense to try to support those in old compilers going forward.
-
class designation question
Remy Lebeau replied to David Schwartz's topic in Algorithms, Data Structures and Class Design
A declaration of an alias, anyway. TMyClass and TAnotherClass will be the same type, as far as the compiler and RTTI are concerned. Now, if you do this instead: TMyClass = type TAnotherClass; Or this: TMyClass = class(TAnotherClass) Then TMyClass will be its own unique type. -
How do we know if the, TCP Socket connection is connected
Remy Lebeau replied to Turan Can's topic in Cross-platform
Because you are merely checking the socket for readability only. If select() returns 0, it timed out, which in this case means the socket is not readable because it has no pending data, not even a graceful disconnect. As long as connect() is successful and the socket doesn't report read/write errors, it is connected. -
How do we know if the, TCP Socket connection is connected
Remy Lebeau replied to Turan Can's topic in Cross-platform
No, it is an undefined method. Calling recv() with a buffer length of -1 is undefined behavior, and AFAICS no platform actually defines what should happen with that input. -
How do we know if the, TCP Socket connection is connected
Remy Lebeau replied to Turan Can's topic in Cross-platform
Cross-platform, the only way is to perform an I/O operation on the socket and check for error. On Windows, at least, a non-blocking socket can issue an asynchronous FD_CLOSE notification when the connection is closed, but you should still check I/O operations for errors, too. The same type of coding will work on POSIX, too. The base BSD socket API, like select() and recv(), is common across multiple platforms. Why are you passing your fd_set variable as the buffer for recv() to read into? More importantly, you can't pass -1 as the size of the buffer to read into. On Windows, the len parameter is an int, so it will at least compile with a length of -1, but semantically asking recv() to read -1 number of bytes makes no sense, and is not documented as a supported operation. But worse, on other platforms, the len parameter is a size_t, which is an unsigned type, so passing in a length of -1 will wrap to a very large value and very bad things can happen! Also, you are not checking to make sure that select() actually reports the socket is readable before then calling recv() on the socket. Since you are only querying 1 socket, the return value of select() will be -1 on error, 0 on timeout (not readable), and 1 (readable). Alternatively, since select() modifies the fd_set struct on output, you can check if your socket is still in the set after select() exits. Also, you are not handling recv() reporting an error at all. Either way, do keep in mind that you are performing an actual read, so any bytes that recv() does actually receive will not be available for subsequent reads, so you will have to buffer the bytes somewhere in memory so you can still use them later. In most cases, implementing an IsConnected() type of function is really unnecessary and should be avoided. -
Difference between FastMM 4.992 and one that comes with Delphi (10.3)
Remy Lebeau replied to Tommi Prami's topic in Delphi Third-Party
Yes. Everyone's situations are different, requiring different FastMM configurations, and most of those settings can't be set dynamically at runtime. So it makes sense for Embarcadero to ship with a minimal configuration and let people upgrade to the full version if they need to customize the settings. Yes, but not everyone uses the same configuration. Full -
Yes, exactly. We're going to be dropping support for old compilers, Delphi and FreePascal alike, which do not support UnicodeString (we are not going to handle WideString). Providing backwards compatibility for AnsiString when Unicode is now part of most modern network protocols, as well as modren RTLs being Unicode-based, has made a real mess of the codebase. We are also dropping support for .NET completely. Indy 11 is intended to be a maintenance release to do some much-needed cleanup.
-
That is because Indy doesn't use batch files anymore for newer Delphi versions (it does for C++Builder, though). You can simply open the 5 DPKs in the Delphi IDE and compile and install them directly. UInt8 (and other (U)IntX data types) are defined for Delphi 2007 and earlier in the IdGlobal.pas unit, which IdBuffer.pas uses. Indy's IdCompilerDefines.inc file defines HAS_UInt8 for Delphi 2009 and later. IdGlobal.pas declares UInt8 when HAS_UInt8 is not defined. So there is no reason for IdBuffer.pas to not know what UInt8 is, whether it comes from Indy's IdGlobal unit or the RTL's System unit. My guess is that you probably have multiple versions of Indy's source code on your computer, and IdBuffer.pas is finding an older version of IdGlobal that does not implement UInt8 for Delphi 2007. Yes. At least until Indy 11 is released (no ETA on that at this time), which will drop support for Delphi 2007 and earlier going forward. Because there isn't one.
-
Firemonkey app for Android - segmantation fault in TIdThreadSafe.Lock
Remy Lebeau replied to Vandrovnik's topic in Indy
Based on the stack trace in the error message, there is a TIdThread object being destroyed during the finalization of the System.Classes unit. Somewhere in your project, there is a TDictionary holding TThread pointers to TIdThread objects, and that dictionary is being destroyed during unit finalization, freeing the threads that it contains. Inside the TIdThread destructor, there is a global TIdThreadSafeInteger object named GThreadCount in Indy's IdThread unit that is being decremented. The TIdThreadSafe... classes have a TCriticalSection object inside of them. So, based on this error, it is fairly clear that *something* in your project is using Indy, even if *you* are not using Indy in your code, and that Indy's IdThread unit is likely being finalized early, freeing the GThreadCount object while there are still 1 or more TIdThread objects running. Whoever is maintaining a dictionary of threads is likely not terminating their threads before your program exits. Note: the GThreadCount object is marked as deprecated in the latest version of Indy on GitHub, so it will be removed eventually, so this won't be a problem anymore. But that does not help you right now. -
Overloaded generic methods
Remy Lebeau replied to chkaufmann's topic in RTL and Delphi Object Pascal
While it is true that you can't pass T itself directly without using a constraint on T, you can use T's RTTI to get its Interface Guid or Class Type at runtime, and then pass that to Supports()/InheritsFrom() instead of T. For example, something like this: uses ..., TypInfo; type TComponentHelper = class helper for TComponent public function FindComponents<T>: IBSEnumerable<T>; end; function TComponentHelper.FindComponents<T>: IBSEnumerable<T>; type PIInterface = ^IInterface; PTComponent = ^TComponent; var ix : Integer; lst : IBSList<T>; tmp : T; comp : TComponent; ClsType: TClass; IntfGuid: TGUID; begin case GetTypeKind(T){PTypeInfo(TypeInfo(T)).Kind} of tkClass: begin lst := TBSGenerics.GenList<T>; ClsType := GetTypeData(PTypeInfo(TypeInfo(T))).ClassType; for ix := 0 to ComponentCount - 1 do begin comp := Components[ix]; if comp.InheritsFrom(ClsType) then begin PTComponent(@tmp)^ = comp; lst.Add(tmp); end; end; end; tkInterface: begin lst := TBSGenerics.GenList<T>; IntfGuid := GetTypeData(PTypeInfo(TypeInfo(T))).Guid; for ix := 0 to ComponentCount - 1 do begin if Supports(Components[ix], IntfGuid, PIInterface(@tmp)^) then lst.Add(tmp); end; end; else raise ...; end; Result := lst; end; -
Overloaded generic methods
Remy Lebeau replied to chkaufmann's topic in RTL and Delphi Object Pascal
You can't overload on return type alone. You need different parameter lists. That is exactly what the error message is saying. So a simple solution would be to change the return value into an output parameter, eg: TComponentHelper = class helper for TComponent public procedure FindComponents<I:IInterface>(out Enum: IBSEnumerable<I>); overload; procedure FindComponents<T:class>(out Enum: IBSEnumerable<T>); overload; end; procedure TComponentHelper.FindComponents<I:IInterface>(out Enum: IBSEnumerable<I>); var ix : Integer; lst : IBSList<I>; tmp : I; begin lst := TBSGenerics.GenList<I>; for ix := 0 to ComponentCount - 1 do begin if Supports(Components[ix], I, tmp) then lst.Add(tmp); end; Enum := lst; end; procedure TComponentHelper.FindComponents<T:class>(out Enum: IBSEnumerable<T>); var ix : Integer; lst : IBSList<T>; tmp : T; comp: TComponent; begin Assert(T.InheritsFrom(TComponent), 'Nur für Subklassen von TComponent'); lst := TBSGenerics.GenList<T>; for ix := 0 to ComponentCount - 1 do begin comp := Components[ix]; if comp.InheritsFrom(T) then lst.Add(T(comp)); end; Enum := lst; end; -
TStringList property in custom class constructor doesn't persist
Remy Lebeau replied to FiftyTifty's topic in General Help
Returned WHERE exactly? WHERE are you expecting the strings to be when you see them missing? Sorry, but given the code you have provided, that is simply not possible. Persisting WHERE exactly? But in the code you have provided, you are doing all of that manually, there is no automated persistence involved. What am I missing here? Where is THAT code? The Save button in the Editor code you provided has no OnClick handler or TAction assigned to it. I see NO CODE saving the object data ANYWHERE. Seriously? How do you NOT know how to work with breakpoints? Debugging is an essential skill for a programmer, and breakpoints are a big part of that. The ShowMessage() calls in the code you have provided are not adequate enough to see what is really happening. They are only being used to show the flow of the code, but not the state of the code. Oh, BTW, I just now saw a bug in one of your ShowMessage() calls: //ShowMessage('Added ItemStatModification to master list! ' + listCEItemStatModification[0].RowName); Needs to be changed to this instead: //ShowMessage('Added ItemStatModification to master list! ' + ceismToAdd.RowName); Or at least to this (though the above is preferred): //ShowMessage('Added ItemStatModification to master list! ' + listCEItemStatModification.Items[iCounter].RowName); Do you see why the original statement was faulty? It is displaying the RowName of the 1st object in the list on every loop iteration, not the RowName of the current object that was just added to the list on each iteration. How do you know that, if you don't know how to use the debugger to actually step through the code in real time and look at the data in memory? Sorry, but given the code you have shown, there is absolutely no possible way that can be happening. That said, I would also like to point out that I see other bugs in your code, too. In particular, if the Load button is clicked multiple times, I see several memory leaks occurring, but more importantly you are not clearing the TreeView of old nodes when you clear the TList (leaking the objects in it!) that backs the TreeView, and before you load the new data into the TreeView. You just keep adding new nodes to the TreeView but never remove them. I think you are misdiagnosing your problem, if your observations are based on the logic bugs I mentioned above, and not due to any failure of the actual reading/saving code. -
TStringList property in custom class constructor doesn't persist
Remy Lebeau replied to FiftyTifty's topic in General Help
This is absolutely a memory leak. You need to get rid of the 2nd TStringList.Create. But you didn't really explain HOW your code fails when you don't make that call. I see nothing in the code you have provided that can be freeing the CEItemStatModification.Modifications object prematurely. I do not see you using a JSON streaming library that saves your objects to a stream, or reads a stream into your objects (so why are you decorating your class fields with JSON attributes?), so I don't see what persistence has to do with anything. You are just going to have to debug your code to find out exactly what is happening. Put a breakpoint inside your constructor, make sure it is being called correctly. Put a breakpoint after the constructor, make sure the newly constructed object is still proper after being constructed. Put breakpoints before and after every step of the code that touches your objects, make sure the objects are still proper after every step. As soon as you find a deviation, STOP, repeat, and trace into the step that didn't act as expected. -
Delphi 10.3.3 - Indy from 0ba2688b Git "Hello World"
Remy Lebeau replied to aehimself's topic in Indy
Yes, that is what it does. The OnConnect, OnDisconnect, OnExecute, and OnException events are called in the context of the connection thread, yes. That is a bit broad to answer. It really depends on how and where they are being used. I'm assuming you are referring to performing per-thread preparations, right? Then it comes down to whether you are using Indy's default 1-thread-per-connection model, or using thread pooling instead. If the former, then the server's OnConnect and OnDisconnect events will usually suffice. If you do not assign any component to the server's Scheduler property, a TIdSchedulerOfThreadDefault component is created and assigned for you automatically when you activate the server. TIdSchedulerOfThreadDefault creates a new thread per connection, and frees each thread when the connections are closed. Thus the server's OnConnect and OnDisconnect events are called only once per thread. If the latter, then as connections are closed and threads get reused, the OnConnect and OnDisconnect events can be called for multiple connections on the same thread, so that wouldn't really be a good place to perform per-thread initializations/cleanups (per-connection, yes). A better option (at least for now) is to derive a new class from TIdThreadWithTask and have it override the virtual BeforeExecute() and AfterExecute() methods to perform per-thread initializations/cleanups as needed, and then you can explicitly assign a TIdSchedulerOfThreadPool component to the server's Scheduler property, and assign your Task class to the TIdSchedulerOfThreadPool.ThreadClass property. Technically, you could take the same Task approach with TIdSchedulerOfThreadDefault, too. But that would generally be overkill, but usable. -
Delphi 10.3.3 - Indy from 0ba2688b Git "Hello World"
Remy Lebeau replied to aehimself's topic in Indy
Closing the client socket while the server is active will still raise an exception on the server side, such as EIdConnClosedGracefully. The debugger can be configured to ignore that exception (IIRC, it already is by default). Deactivating the server while the client is still connected will close the socket connected to the client, and thus will usually also raise an exception on the server side if the OnExecute event is still blocked on a read/write operation. You have it backwards. The first triggering of the OnExecute will successfully read your initial text from the socket, the second triggering will not until you send more text. -
Delphi 10.3.3 - Indy from 0ba2688b Git "Hello World"
Remy Lebeau replied to aehimself's topic in Indy
That is because they have not been created and checked in yet. -
Delphi 10.3.3 - Indy from 0ba2688b Git "Hello World"
Remy Lebeau replied to aehimself's topic in Indy
This is normal behavior! Your client is sending only 1 line of text. The server's OnExecute event is looped, and so it tries to read 2 lines. There is no data for the 2nd read is receive, so it blocks the calling thread waiting for new data that will never arrive, until the client disconnects or the server is deactivated. At which time, the blocked read will then fail and raise a socket exception. Let it happen that way! The server will handle the exception for you and stop the thread that called the OnExecute event. You will see the exception only if you are running your code in the IDE's debugger (and have not configured the debugger to ignore the exception), or have assigned a handler to the server's OnException event. This is how Indy is designed to work! To help illustrate this better, you should move your client's IOHandler.Write() call into a button OnClick event, and then press it multiple times while the TIdTCPClient is connected to the server, like Kryvich described (though I would have used separate buttons for Connect, Disconnect, and Write()). You will see the ReadLn() call unblock with each button click. Then you should read Introduction to Indy. No. You already have it. It doesn't get much simpler than what you already have. -
Different build targets, different set of options. Same thing with Windows 32bit/64bit, iOS 32bit/64bit, OSX 32bit/64bit, etc.
-
They roughly translate to: uygulamasinin telefon etmesine ve cagrilan yonetmesine izin verilsin mi? Allows the app to phone and manage the call? Telefon arama kayitlariniza erismek icin Permissions uygulamasina izin verilsin mi? Allow Permissions to access your phone call logs?