-
Content Count
3056 -
Joined
-
Last visited
-
Days Won
139
Everything posted by Remy Lebeau
-
Playing an MP4 animation / unsupported media file / cppbuilder
Remy Lebeau replied to alank2's topic in FMX
That error happens if TMediaPlayer can't instantiate DirectShow's Graph Builder object (did you initialize the COM library beforehand?), or can't query the builder for the necessary video renderer interfaces, or the builder can't load the file to render it. -
I don't understand what this log is supposed to be showing me. Looks like every request received is responded to, and each connection is closed. What am I missing? What is the actual problem, exactly? Using HTTPS through an HTTP proxy requires use of the CONNECT verb, which is just a straight passthough tunnel of raw data from the client to the target server and back. TIdHTTPProxyServer does not attempt to interpret the raw data in any way, all it is doing is managing the 2 TCP connections involved. Whereas, using HTTP through an HTTP proxy requires sending HTTP requests to the proxy itself, and then the proxy makes its own HTTP requests to the target server. So TIdHTTPProxyServer by default is fully reading and interpreting your client's requests and then replicating them to the target server. So sure, there could certainly be some glitches in that process. TIdHTTPProxyServer is not a full HTTP server or HTTP client, it is quite bare-bones, so it is not outside the realm of possibility that RemObjects is sending its HTTP requests in a way that TIdHTTPProxyServer can't handle correctly. Or, because TIdHTTPProxyServer uses HTTP 1.0 when communicating with the target server, there could be differences between its use of HTTP 1.0 and the client's use of HTTP 1.1 that is causing interference. Hard to say for sure. I'm speculating, because I have no way to actually test/debug this at the moment. Something else to consider - by default, TIdHTTPProxyServer.DefaultTransferMode is set to tmFullDocument, which means for GET/POST/HEAD requests, TIdHTTPProxyServer will read the client's entire request into memory before then passing it along to the target server, and then read the server's entire response into memory before then passing it along to the client. This allows the user's application code to modify the request/response data if desired before passing it along. Do you have the same problem if you set TIdHTTPProxyServer.DefaultTransferMode to tmStreaming instead? That will cause TIdHTTPProxyServer to not buffer the request/response data in memory, it will be passed along as it is being received (at the cost that application code can't modify it anymore).
-
Delphi CE 10.4.2 - Command Line Compilation
Remy Lebeau replied to PawelPepe's topic in Delphi IDE and APIs
Well, that sucks -
exceptions and static storage duration objects
Remy Lebeau replied to Fraser's topic in General Help
I'm just going off of the actual code you posted earlier. That tends to happen when the runtime/debugger can't interpret the actual exception object at the level it was detected at, basically treating it as an "unknown" exception type. Did you not see the quote I posted earlier? https://en.cppreference.com/w/cpp/language/function-try-block Minor nitpicks: the A() constructor is not public, and std::exit() takes an exit code integer instead of a string as input. In any case, when I test the code outside of C++Builder (which I don't have installed at the moment), the code works fine when using std::exit() in the function-try's catch handler: https://onlinegdb.com/WqiBtg8dD https://onlinegdb.com/v7B8acNo4 And terminates the process with a re-thrown exception when not using std::exit() in the handler: https://onlinegdb.com/q0KLc6Cne https://onlinegdb.com/rHqvw5kmo -
Playing an MP4 animation / unsupported media file / cppbuilder
Remy Lebeau replied to alank2's topic in FMX
What is the actual error? What version of C++Builder are you using, and what platform(s) are you attempting to play the MP4 on? Did you verify the MP4 is valid to begin with? Can you play it with other software players? What kind of artifacts? -
delphi LabView DLL creates weird double array
Remy Lebeau replied to Snieres's topic in Algorithms, Data Structures and Class Design
I just answered that on StackOverflow, go see my update. -
delphi LabView DLL creates weird double array
Remy Lebeau replied to Snieres's topic in Algorithms, Data Structures and Class Design
<sigh> And here we go again... This is a followup to these StackOverflow questions: https://stackoverflow.com/questions/73313071/ https://stackoverflow.com/questions/73254575/ -
Good example of what exceptions TIdHTTP cielt can raise
Remy Lebeau replied to Tommi Prami's topic in Indy
Indy has a few hundred unique exception classes defined, so it is not really feasible to give you a comprehensive list of them all. However, most of them are specialized to specific components only, so you don't have to worry about most of them. All Indy exceptions are derived from EIdException. And then for TIdHTTP specifically, you could potentially get any of the following derived exceptions raised (this is not an exhaustive list, there might be others I missed): EIdHTTPProtocolException (HTTP error response from server) EIdUnknownProtocol (requesting a non-HTTP/S URL with no target port specified) EIdIOHandlerPropInvalid (requesting HTTPS URL but no SSLIOHandler is assigned) EIdReadTimeout EIdSocketError (base class for all socket-related exceptions, may also be raised as-is) EIdInternetPermissionNeeded (Android only, for now) EIdConnClosedGracefully EIdClosedSocket EIdNotConnected EIdNotASocket What is wrong with just catching Exception/EIdException and displaying its Message property? Mosst Indy exceptions have message texts assigned to them. -
In which case, you should be getting an EConvertError exception raised, not a corrupted/empty file created.
-
exceptions and static storage duration objects
Remy Lebeau replied to Fraser's topic in General Help
There is no call to exit() in the code you presented. In the code you presented, you have 2 separate object instances of the A class: A a; // <-- here A & AccessA() { static A obj; // <-- here return obj; } The 1st object is being created in global scope during program startup, and the 2nd object is being created in static memory the first time AccessA() is called at runtime. The global object is created before your project's WinMain() function is executed The code presented is not calling AccessA() at all, so the compiler/linker is free to optimize it away, if it wants to. I already explained that in detail in my previous reply. Go re-read it again more carefully. Do you understand the difference between a function-try block and a normal non-function-level try block? No, there is no explicit re-throw statement in the catch block. But the catch block is performing an implicit re-throw, because you are using a function-try block instead of a normal try block: If you really want to swallow the exception, use a normal try block instead of a function-try block, eg: class A { A() noexcept { try { throw std::logic_error("test"); } catch (std::exception const &ex) { std::cout << "Caught an STL exception" << std::endl; } } }; Notice the try-catch is now inside the constructor's body, rather than around the body as in your original example. -
That is normal behavior. That is also normal behavior. Calling conventions like cdecl and stdcall simply don't exist in 64bit, and they are ignored completely when used in code. There is only 1 standardized 64bit calling convention, and its behaviors are dictated by the 64bit ABI. And the 64bit calling convention indeed does not use the same name mangling rules that the 32bit cdecl calling convention uses. Use a .DEF file to control how the linker (or IMPLIB tool) formats exported names, and what internal names those exported names map to.
-
exceptions and static storage duration objects
Remy Lebeau replied to Fraser's topic in General Help
I would not have expected this code to compile, but if it does then it has undefined behavior. You are using a function-try block around the constructor body. Even though you are catching an exception, a function-try implicitly re-throws every exception it catches, if you don't explicitly re-throw it yourself. But you marked the constructor as noexcept, promising it will never throw an exception. You broke the promise. At the very least, you need to get rid of the noexcept to get rid of the undefined behavior. You will still crash at startup, but that is because of another issue... Because the thrown exception is not actually being fully caught. You are constructing an A object in global scope before Winmain() is called, you are not waiting for AccessA() to be called first. That global object is throwing an exception that is not being caught, thus aborting the process startup. A thrown exception that is not caught by the throwing thread causes std::terminate() to be called, which ends the calling process. Likewise, if an exception escapes a noexcept function without being caught, std::terminate() is called as well. But the exception is not being swallowed by the catch handler, it is being re-thrown. -
You can't assign a WAN IP to a printer on the LAN side. If you are trying to access your LAN printer over the public Internet, you will have to setup port forwarding on your router to route incoming connections from a WAN IP/Port to the printer's LAN IP/Port. Then, as others have mentioned, there are plenty of external services you can query to get your current WAN IP. Otherwise, a better option is to just create a VPN into your LAN network, and then use the printer's LAN IP.
-
duplicate thread:
-
That is already set to True by default in new projects, but defaults to False in older projects migrated to newer IDEs.
-
I can't attest to the behavior of the OK and Cancel buttons. But one problem I see is your NewString variable. Where is it declared, and where is it used after the dialog closes? Remember, this dialog is asynchronous, so make sure you are not accessing NewString out of scope. Also, your 'with ASyncService' block is being wasted and should be removed.
- 9 replies
-
- fmx
- tdialogservice
-
(and 1 more)
Tagged with:
-
What is the meaning of the square bracket in here?
Remy Lebeau replied to stacker_liew's topic in RTL and Delphi Object Pascal
The question was about the SQUARE brackets (Attribute), not the ANGLE brackets (Generic). -
exceptions and static storage duration objects
Remy Lebeau replied to Fraser's topic in General Help
Without an example showing the error in action, it is hard to diagnose this. -
What is '<.' ? What is 'mrOK2'? Did you mean 'if AResult <> mrOK then ...' instead?
- 9 replies
-
- fmx
- tdialogservice
-
(and 1 more)
Tagged with:
-
how to flush buffers on Indy components
Remy Lebeau replied to al17nichols's topic in Network, Cloud and Web
Unless your communication protocol is specifically designed to allow resyncing communications without closing the socket, then this is usually not a viable option. What does your protocol actually look like? How are your messages delimited? What does your "disrupted flow of data" look like? At the very least, it is possible to discard bytes only until the next message delimiter is reached. But you won't know if you discarded a (partial) message that was important to your communications, so resyncing via a reconnect is usually the best option. -
how to flush buffers on Indy components
Remy Lebeau replied to al17nichols's topic in Network, Cloud and Web
FYI, your use of the TIdIOHandler.ReadFromSource() method is just mirroring what the public TIdIOHandler.CheckForDataOnSource() method does internally, so you don't really need your TIdIOHandlerHelper class at all, just use CheckForDataOnSource(1) instead of ReadFromStack(False, 1, False). -
how to flush buffers on Indy components
Remy Lebeau replied to al17nichols's topic in Network, Cloud and Web
Unless the data is structured in such a way that you can definitively identify, from ANY point within the data, where the data ends and the next piece of communication begins, then "flushing" the existing data to resume communications is usually not a viable option. Especially if the next piece of communication has already been received and buffered and waiting for your code to read it from the buffer. Are you using a standard protocol like FTP for the transfer, or are you using a custom protocol? Unless the exception is a socket error, then you don't know the actual state of the socket, or how the data was buffered by the socket or by Indy. So, once the exception occurs, usually the only sane thing to do is to just disconnect and reconnect to restart communications fresh, yes. This is true for any TCP library, it is not limited to just Indy. Since you know how much data you transferred before the exception, you can resume the transfer from that position, if your system allows for resuming. -
how to flush buffers on Indy components
Remy Lebeau replied to al17nichols's topic in Network, Cloud and Web
I don't really understand what you are asking for, but why would you ever need something like this? Please provide a use-case example. No (if such a flush were possible). By default, there is no write buffering beyond the send buffer that is built-in to the underlying socket at the OS layer. You can't "flush" that buffer, but you can reduce its size with the SO_SNDBUF socket option, or disable/avoid it with the TCP_NODELAY socket option (Indy's UseNagle property). On top of that, Indy does provide an application-level send buffer via the IOHandler.WriteBuffer...() methods. That buffer is flushed to the socket when the specified threshold is reached, or when WriteBufferFlush() or WriteBufferClose() is called. That buffer can be discarded with WriteBufferCancel(). Read buffering is a bit trickier. There is the receive buffer that is built-in to the underlying socket at the OS layer. You can't "flush" that buffer, only reduce its size with the SO_RCVBUF socket option. On top of that is the application-level buffering that Indy implements via the IOHandler.InputBuffer property, where the IOHandler.RecvBufferSize property controls how many bytes Indy attempts to read from the socket's receive buffer into the InputBuffer at a time. Once data is in the InputBuffer, you can "flush" that buffer by calling its Clear() or Remove() method (in the latter case, you could use the IOHandler.Discard() method instead). So, what is it that you really want to "flush", exactly? What is the scenario that you feel "flushing" is the solution for? -
No (plus, that would require changing and recompiling the code, in which case you may as well just take out the offending code to begin with). But, you can accomplish something similar using breakpoints instead. Put a breakpoint at the beginning of the function, go into its properties, and disable the 'Break' option, and enable the 'Ignore subsequent exceptions' option. Then, put another breakpoint at the end of the function, go into its properties, and disable the 'Break' option, and enable the 'Handle subsequent exceptions' option.
-
You have the call to ShowDialogAfterTaskFinishes() in the wrong place. TTask runs asynchronously, but you are calling ShowDialogAfterTaskFinishes() immediately after the TTask object is created (and possibly before the TTask even begins to run). You need to move the call to ShowDialogAfterTaskFinishes() inside of the TTask procedure itself, similar to what you have for the call to UpdateMainWindow(), eg: procedure TfQBDailyInvoices.TransferEvent; begin TTask.Run( procedure var x: Integer; begin try for x := 0 to qInvoice.RecordCount - 1 do begin DidWorkorderTransfer := ProcessInvoice; TThread.Synchronize(nil, procedure begin { Update User Interface } UpdateMainWindow; end ); qInvoice.Next; end; finally TThread.Queue(nil, ShowDialogAfterTaskFinishes); end; end ); end; Alternatively, you can use TThread.CreateAnonymousThread() instead, so you can use the TThread.OnTerminate event (which is Synchronize()'d with the main UI thread), eg: procedure TfQBDailyInvoices.TransferEvent; var Thread: TThread; begin Thread := TThread.CreateAnonymousThread( procedure var x: Integer; begin for x := 0 to qInvoice.RecordCount - 1 do begin DidWorkorderTransfer := ProcessInvoice; TThread.Synchronize(nil, procedure begin { Update User Interface } UpdateMainWindow; end ); qInvoice.Next; end; end ); Thread.OnTerminate := TransferEventThreadTerminated; Thread.Start; end; procedure TfQBDailyInvoices.TransferEventThreadTerminated; begin ShowDialogAfterTaskFinishes; end; :