Jump to content

Remy Lebeau

Members
  • Content Count

    2914
  • Joined

  • Last visited

  • Days Won

    130

Everything posted by Remy Lebeau

  1. Remy Lebeau

    Indy10 rev 3627 into D10.3.3?

    It shouldn't matter. Delphi defines it with a leading underscore, Indy does not. Delphi should have another statement that maps _IP_ADAPTER_ADDRESSES to IP_ADAPTER_ADDRESSES.
  2. Remy Lebeau

    Indy10 rev 3627 into D10.3.3?

    That clearly shows that the IfIndex field is present in Delphi's definition of IP_ADAPTER_ADDRESSES, as it should be. I don't know what else to tell you then. If you load up Indy's IndySystem package in the IDE and Ctrl-Click on PIP_ADAPTER_ADDRESSES in the IdStackWindows.pas code, where does it take you?
  3. Remy Lebeau

    Indy10 rev 3627 into D10.3.3?

    Refresh and look at my updated previous reply
  4. Remy Lebeau

    Indy10 rev 3627 into D10.3.3?

    But, did you validate whether Delphi's definition of IP_ADAPTER_ADDRESSES has IfIndex or not? I don't have access to the RTL's IpTypes.pas source file right now to look myself, I'll do that tomorrow. Indy should not be accessing any 3rd party IpTypes unit. But, that is why I did say to make sure that is not happening (did you read that link yet?): If HAS_UNIT_IpTypes is defined, then try making that same change to IdStackWindows.pas. But, if HAS_UNIT_IpTypes is not defined, then that doesn't matter, and you should not be getting the error since Indy does define the IfIndex field in its own definition of the IP_ADAPTER_ADDRESSES record: IP_ADAPTER_ADDRESSES = record Union: record case Integer of 0: ( Alignment: ULONGLONG); 1: ( Length: ULONG; IfIndex: DWORD); // <-- HERE!!!!! end; Next: PIP_ADAPTER_ADDRESSES; AdapterName: PIdAnsiChar; FirstUnicastAddress: PIP_ADAPTER_UNICAST_ADDRESS; FirstAnycastAddress: PIP_ADAPTER_ANYCAST_ADDRESS; FirstMulticastAddress: PIP_ADAPTER_MULTICAST_ADDRESS; FirstDnsServerAddress: PIP_ADAPTER_DNS_SERVER_ADDRESS; DnsSuffix: PWCHAR; Description: PWCHAR; FriendlyName: PWCHAR; PhysicalAddress: array [0..MAX_ADAPTER_ADDRESS_LENGTH - 1] of BYTE; PhysicalAddressLength: DWORD; Flags: DWORD; Mtu: DWORD; IfType: IFTYPE; OperStatus: IF_OPER_STATUS; Ipv6IfIndex: IF_INDEX; ZoneIndices: array [0..15] of DWORD; FirstPrefix: PIP_ADAPTER_PREFIX; TransmitLinkSpeed: ULONG64; ReceiveLinkSpeed: ULONG64; FirstWinsServerAddress: PIP_ADAPTER_WINS_SERVER_ADDRESS_LH; FirstGatewayAddress: PIP_ADAPTER_GATEWAY_ADDRESS_LH; Ipv4Metric: ULONG; Ipv6Metric: ULONG; Luid: IF_LUID; Dhcpv4Server: SOCKET_ADDRESS; CompartmentId: NET_IF_COMPARTMENT_ID; NetworkGuid: NET_IF_NETWORK_GUID; ConnectionType: NET_IF_CONNECTION_TYPE; TunnelType: TUNNEL_TYPE; // // DHCP v6 Info. // Dhcpv6Server: SOCKET_ADDRESS; Dhcpv6ClientDuid: array [0..MAX_DHCPV6_DUID_LENGTH - 1] of Byte; Dhcpv6ClientDuidLength: ULONG; Dhcpv6Iaid: ULONG; FirstDnsSuffix: PIP_ADAPTER_DNS_SUFFIX; end;
  5. Remy Lebeau

    Indy10 rev 3627 into D10.3.3?

    OK
  6. Remy Lebeau

    Indy10 rev 3627 into D10.3.3?

    See Support for Subversion clients in GitHub's documentation. Now that Indy is on GitHub, SVN revision numbers don't really have any meaning to Indy anymore. There is no readily available mapping of GitHub's SVN revision numbers to GIT commits within the GIT system, so when you say "svn rev XYZ", I don't know which GIT commit that actually refers to, unless I go access the system via SVN and look at the metadata. Just saying...
  7. Remy Lebeau

    Indy10 rev 3627 into D10.3.3?

    There is no /trunk folder in GitHub. Did you even try the fix I posted last night for you? The AdapterIndex error should be fixed now. Regarding the IfIndex error, Indy manually defines the IP_ADAPTER_ADDRESSES record only when HAS_UNIT_IpTypes is not defined. HAS_UNIT_IpTypes is defined for XE2+, and 10.3 is later than XE2, which means Indy is going to use an external (hopefully Delphi's!) definition of IP_ADAPTER_ADDRESSES rather than Indy's definition. It would stand to reason that the external definition lacks the IfIndex field (why, I don't know), otherwise you wouldn't be getting an error on it. Double-check Delphi's definition in the RTL's Winapi.IpTypes.pas unit is accurate, and also make sure you are not falling into this trap. In the meantime, a simple workaround would be to just comment out the {$DEFINE HAS_UNIT_IpTypes} statement in IdStackWindows.pas for now.
  8. Remy Lebeau

    Indy10 rev 3627 into D10.3.3?

    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.
  9. Remy Lebeau

    Android Mobile application using Firemonkey

    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.
  10. Remy Lebeau

    Tool to fix up uses clause unit namespaces?

    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.
  11. Remy Lebeau

    Receiving incoming calls

    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;
  12. 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.
  13. 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.
  14. Remy Lebeau

    Delphi 2007 supported in Indy 10?

    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.
  15. Remy Lebeau

    class designation question

    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.
  16. 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.
  17. 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.
  18. 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.
  19. 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
  20. Remy Lebeau

    Delphi 2007 supported in Indy 10?

    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.
  21. Remy Lebeau

    Delphi 2007 supported in Indy 10?

    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.
  22. 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.
  23. Remy Lebeau

    Overloaded generic methods

    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;
  24. Remy Lebeau

    Overloaded generic methods

    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;
  25. 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.
×