Jump to content

Remy Lebeau

Members
  • Content Count

    2417
  • Joined

  • Last visited

  • Days Won

    97

Remy Lebeau last won the day on July 20

Remy Lebeau had the most liked content!

Community Reputation

1293 Excellent

Technical Information

  • Delphi-Version
    Delphi 12 Athens

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Remy Lebeau

    Avoid parameter evaluation

    Not quite. You have implemented DoProcess() incorrectly, causing undefined behavior. The code compiles, but it will not behave correctly at runtime for certain types. For instance, try passing a single Char into it and your code will crash. That approach is wrong. You cannot treat all of those types the same way, as they are stored in different ways in the array. vtChar and ctWideChar are stored as individual values in the array itself (like integers are), whereas vtString is a pointer to a ShortString variable, whereas vtAnsiString and vtUnicodeString are copies of the data block pointer from inside of an AnsiString/UnicodeString instance, etc. You need to handle the various types individually and correctly, eg: procedure DoProcess(const Args: array of const); var i: Integer; begin for i := Low(Args) to High(Args) do begin case Args[i].VType of vtString: Writeln(Args[i].VString^); vtChar: Writeln(Args[i].VChar); vtPChar: Writeln(Args[i].VPChar); vtWideChar: Writeln(Args[i].VWideChar); vtPWideChar: Writeln(Args[i].VPWideChar); vtAnsiString: Writeln(AnsiString(Args[i].VAnsiString)); vtWideString: Writeln(WideString(Args[i].VWideString)); vtUnicodeString: Writeln(UnicodeString(Args[i].VUnicodeString)); vtInteger: Writeln(Args[i].VInteger); vtInt64: Writeln(Int64(Args[i].VInt64)); else Writeln('Type handling not implemented yet ' + IntToStr(Args[i].VType)); end; end; end; Also, see the MakeStr() example in this earlier post:
  2. Remy Lebeau

    Avoid parameter evaluation

    Since performance is in question, I would suggest taking this approach a step further and use 'array of const' instead of 'array of string'. That way, you can pass in integers and other fundamental types as-is and not invoke the overhead of converting them to strings unless you are sure you actually need to, eg: procedure Log(LogLevel: TLogLevel; const Args: array of const); overload; begin if CanLog(LogLevel) then begin // convert Args to a log message and write it out as needed... end; end; Log(llTrace, ['Test', GetLastError(), ...]);
  3. Remy Lebeau

    Avoid parameter evaluation

    FreePascal supports preprocessor macros; https://www.freepascal.org/docs-html/3.2.0/prog/progse5.html For Delphi, you would have to write/find an external tool to preprocess your code before compiling it.
  4. Remy Lebeau

    How to check for Delphi update?

    Because only 1 patch has been released so far. And that was for 12.0, not for 12.1. Correct. Point releases usually require a full uninstall and reinstall. You can't do that with Getit from within the IDE (but the installer uses GetIt technology). Patches can update an existing installation, so it makes sense that they can be distributed via GetIt. You can login to your account at https://my.embarcadero.com to download the 12.1 installer. Feel free to file a feature request at https://qp.embarcadero.com
  5. I'm not sure I understand. Are you saying that when you go to start a new project, there is no VCL option provided? If so, then maybe your installation is messed up, or maybe you are using Kylix instead of D7. Hard you say. Can you provide screenshots of what you are actually seeing?
  6. Remy Lebeau

    System.Net.Socket: TSocket.BeginReceive timeout

    If you don't want to ignore all socket exceptions, you can use breakpoints to tell the debugger to ignore the exceptions only for particular sections of code. And even use breakpoints to toggle when other breakpoints are enabled/disabled. Breakpoints have quite a few useful features beyond just stopping execution when they are hit. It is still available, it is just not installed by default. See https://docwiki.embarcadero.com/RADStudio/en/Installing_Socket_Components
  7. Remy Lebeau

    System.Net.Socket: TSocket.BeginReceive timeout

    Not to sound gloomy, but I have yet to see Borland/CodeGear/Embarcadero produce a good solid cross-platform socket library. There is always problems in their implementations. Back in the day, CLX's sockets were notoriously buggy. The Windows-only ScktComp unit is pretty solid (if you ignore its bad handling of Unicode text and TStream - the rest of it is good, though). The traditional approach is to use either 1) synchronous socket I/O, 2) non-blocking socket I/O with select() or (e)poll(), or 3) OS-specific notifications. WinSock on Windows provides notifications via window messages (which ScktComp handles). Most other platforms don't offer notifications, so that leaves blocking or polling. In this case, TSocket.BeginReceive() is using a combination of #1 and #2 - it uses a TTask thread to perform a blocking read, but it also uses select() to wait for new bytes to arrive before then reading them. The problem is that ReceiveTimeout is 0 by default, and comments in the implementation say both 0 and -1 are supposed to be infinite, but 0 is not actually treated as infinite. It is used for polling, but polling timeouts are being treated as failures like any other. If any timeout error occurs then the read operator is over, it doesn't keep polling. Unless you are handling the failure and calling BeginReceive() again? You could just tell the debugger to ignore the errors. Why would they not be allowed, in what? Possibly. I've never had much trouble with ScktComp (and things it does have problems with are easily worked around).
  8. In addition to what others said - it is unusual to get an AccessViolation due to Execution of an address, usually it is due to a Read or Write instead. If you are executing code at a bad memory address, that means you tried to call a function via a corrupted function pointer, or something like that, which will be much more difficult to find. If it were just a read/write error, the error message would also give you the memory address of the code that tried to access the bad memory, so you could more easily jump right to that code.
  9. Remy Lebeau

    Indyclient help

    Then you are using an outdated version of Indy and should upgrade. The ReadUInt16() method was added almost a decade ago, in Delphi XE8. In the meantime, you can use the older ReadWord() method instead. That calculation is wrong. You need to multiple by 256 ($100), not by 16 ($10). Better to just use ReadWord()/ReadUInt16() instead. True means it will append the read bytes to the end of the TIdBytes. False means it will store the read bytes at the beginning of the TIdBytes, and will grow the TIdBytes if it is too small.
  10. Remy Lebeau

    Stand alone EXE

    Not a whole lot, unfortunately. Trimming the debug info helps a lttle, but most of the size is just RTL bloat, Unicode, DFMs, RTTI, etc. In Delphi, it is possible to reduce some of the RTTI a little, but not in C++Builder, AFAIK.
  11. Remy Lebeau

    Stand alone EXE

    That is to be expected with a standalone EXE. It should not need those DLLs if you have disabled all of the options I mentioned earlier. Are you sure you did it in all of your build configurations? Did you do a full rebuild? Are you sure you are simply not running an older version of the EXE? To run a single EXE on both types of PCs, you have to compile the EXE for 32bit only, not for 64bit. Make sure you have the 32bit platform active in your project's Target Platforms settings.
  12. Remy Lebeau

    Indyclient help

    In that case, your code logic is wrong. You are throwing away one of the length bytes, so you will only be able to handle packets up to 256 bytes max. And, based on the examples provided, you should not be subtracting -1 from the length, either. You are ignoring the last byte in the payload. Try this instead: var s: string; len: UInt16; ... try if IdTCPClient1.IOHandler.InputBufferIsEmpty then begin if not IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then Exit; end; len := IdTCPClient1.IOHandler.ReadUInt16; s := IdTCPClient1.IOHandler.ReadString(len); Memo1.Lines.Add(s); Timer4.Enabled := false; except end; Fair enough, though I would still not advise doing that on the main UI thread to begin with. Only for packets with payloads up to 255 bytes in size. Larger payloads will not have a zero as the 1st byte. This protocol allows for payloads up to 65535 bytes in size.
  13. Remy Lebeau

    Android, any way to use the device's existing fonts?

    There is nothing built-in to FMX for retrieving the device's fonts. I've seen 3rd party solutions that provide FMX wrappers for OSX and Windows, but not for Android. Android does have some APIs you can try directly, see: https://stackoverflow.com/questions/3532397/how-to-retrieve-a-list-of-available-installed-fonts-in-android
  14. Remy Lebeau

    Indyclient help

    FYI, there is an Indy-specific forum on this site: https://en.delphipraxis.net/forum/35-indy/ It is hard to answer that without knowing any details about the particular specification you are coding against. If you are expecting a response immediately after writing, then why are you using a Timer? Just read and let it block. If you are doing this from the main UI thread and don't want to block the UI, then use a worker thread. Why do you keep clearing the IOHandler.InputBuffer when it is already empty? Why are you discarding the 1st byte? What does it represent? FYI, you can replace your entire loop with a single call to Indy's BytesToString() function, eg: var Buffer: TIdBytes; ... IdTCPClient1.IOHandler.ReadBytes(Buffer, bajt - 1, False); s := BytesToString(Buffer); Or, you could just use IOHandler.ReadString() instead of IOHandler.ReadBytes(), eg: s := IdTCPClient1.IOHandler.ReadString(bajt - 1);
  15. Remy Lebeau

    Stand alone EXE

    For both Delphi and C++: Project > Options > Packages > Runtime Packages "Link with runtime packages" = false If you are making a C++ project, you'll also need: Project > Options > Building > C++ Linker "Link with Dynamic RTL" = false "Link with the Delphi Runtime Library" = false Note that with these settings, Packages will be built into the EXE so you don't have to deploy any BPLs. But, if your code (or any of its dependencies) require external DLLs, you will still have to deploy those with your EXE. At the bare minimum, you could just zip up all of the binaries and extract them to a folder on the target machine. But why would you not want to use a setup package that handles this for you?
×