-
Content Count
2721 -
Joined
-
Last visited
-
Days Won
119
Everything posted by Remy Lebeau
-
"Gotchas" when calling from a C DLL to a Delphi DLL?
Remy Lebeau replied to Dave Nottage's topic in General Help
No, it is not. And besides, your IntToStr() has undefined behavior anyway. You should get rid of that function and just use sprintf() directly in your HandleException(). But that is beside the point. That implies to me that possibly either: there is a calling convention mismatch in how DelphiDriverOpen() is declared in both languages. the Delphi DLL is corrupting the call stack. an uncaught exception is being thrown. You will have to use the debugger to verify one way or the other. -
Blogged : Delphi Package Manager RFC
Remy Lebeau replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
You SHOULD already be able to have per-project packages, in all versions of Delphi. The trick is to install the packages but NOT ENABLE them globally. With no project loaded, install the packages as needed, and then disable them so they don't appear in the Palettes when no project is loaded. Then, load a project, enable only the installed packages it actually needs, and close the project. Repeat as needed for other projects. Then, from now on, the IDE should load and unload packages on a per-project basis. At least, this is how it used to work years ago, I haven't tried it in recent years. Hopefully it still works. -
"Gotchas" when calling from a C DLL to a Delphi DLL?
Remy Lebeau replied to Dave Nottage's topic in General Help
That would imply that the Delphi DLL is not coded properly for the Citrix driver API, since Delphi can certainly produce C-compatible DLLs. Aside from that, the only thing I see wrong in your Delphi translation is that HND should be a Pointer instead of a THandle, and pLibMgrCallTable should be a Pointer instead of a ^DWORD. However, you did not show your translation of the PVD type, or of the DriverOpen() and other DLL function declarations. Since Citrix is complaining about an invalid handle, did you debug your C and Delphi DLLs to log the value of the handle that DriverOpen() actually returns, and the value of the handle that the other DLL functions receive? Where exactly does DriverOpen() return the handle to - the 'int' return value, or in the PVD parameter? -
Your translation is WAY off. DONT use String for char* parameters, use PAnsiChar instead. DONT use Integer for (D)WORD parameters, use (D)WORD instead. And your handle parameter needs to be declared as 'var' or 'out' since it is an output parameter. Try this instead: function MXEIO_E1K_Connect(szIP: PAnsiChar; wPort: WORD; dwTimeOut: DWORD; var hConnection: Integer; szPassword: PAnsiChar): Integer; stdcall; external 'MXIO.dll' name 'MXEIO_E1K_Connect'; Or this: function MXEIO_E1K_Connect(szIP: PAnsiChar; wPort: WORD; dwTimeOut: DWORD; hConnection: PInteger; szPassword: PAnsiChar): Integer; stdcall; external 'MXIO.dll' name 'MXEIO_E1K_Connect';
-
The DLL's documentation includes VB declarations. VB doesn't support cdecl at all, only stdcall. Also, I just found this, which clearly shows the DLL functions using CALLBACK for the calling convention. That is a preprocessor macro that maps to __stdcall.
-
In general, when creating a URL by hand, I suggest NOT using TIdURI.URLEncode() on the entire URL, but instead use TIdURI.PathEncode() and TIdURI.ParamsEncode() on individual components that actually need to be encoded. Also, the default encoding for TStringStream is the OS default charset, but JSON typically uses UTF-8 instead. If you know the actual charset the server uses for the response, you could hard-code it in the TStringStream constructor. But, it is generally better to just let TIdHTTP handle charset decoding of strings for you instead. Try something more like this: var http : TIdHTTP; sslIO : TIdSSLIOHandlerSocketOpenSSL; url, data : String; begin http := TIdHTTP.Create(nil); try http.HTTPOptions := http.HTTPOptions + [hoNoProtocolErrorException, hoWantProtocolErrorContent]; sslIO := TIdSSLIOHandlerSocketOpenSSL.Create(http); sslIO.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2]; sslIO.SSLOptions.Mode := sslmClient; sslIO.SSLOptions.VerifyMode := []; sslIO.SSLOptions.VerifyDepth := 0; http.IOHandler := sslIO; url := 'https://translate.googleapis.com/translate_a/single?client=gtx&sl=de&tl=ru&dt=t&q=' + TIdURI.ParamsEncode('Müller'); data := http.Get(url); finally http.Free; end; end;
-
Blogged : Delphi Package Manager RFC
Remy Lebeau replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
FreePascal already has its own Online Package Manager built right into the Lazarus IDE. -
You can't, as TPaintBox is painted dynamically on an as-needed basis, so there is no persistent image to "capture". You need to change your drawing code to draw onto a TBitmap (or any arbitrary TCanvas) instead, and wrap that code into a function that you can call whenever needed. That way, when the TPaintBox needs to be painted, create a temp TBitmap, have the function draw onto it, and then draw that TBitmap onto the TPaintBox. When you want to do the "capture", create another temp TBitmap, have the function draw onto it, and then use the TBitmap as needed. This applies to both VCL and FMX, BTW.
-
TIdMessageBuilderHtml add background color
Remy Lebeau replied to azrael_11's topic in Network, Cloud and Web
That has nothing to do with Indy, and everything to do with your particular HTML/CSS, and whether the receiver supports what you are trying (for instance, not all email readers support background images - see The Ultimate Guide to Background Images in Email ). Indy does not care about the particular content of your HTML, it gets sent as-is (other than to encode it for transmission purposes only). I will say this, though: - in your 1st case, 'url("back,png")' is wrong for an embedded image, you need to use 'url("cid:back.png")' instead since "back.png" is the Content-ID you assigned to the attachment. - in your 2nd case, the 3rd call to Html.Add() appears to be broken. -
Does application.processmessages behaviour differ between VCL and FMX?
Remy Lebeau replied to Incus J's topic in RTL and Delphi Object Pascal
There is nothing wrong with using threads in general, you just have to understand WHEN and HOW to use them effectively. You can't write really high performant software without them. Especially on mobile platforms. I've been writing commercial software for 20 years as well, and have written many multi-threaded applications, just using Delphi's 'TThread' class. I don't use a version that has Embarcadero's "Parallel Processing Library" available (I would never trust it anyway, it has had too many bugs over the years!), and I don't use 3rd party threading libraries, like OmniThreadLibrary, etc (not that there is anything wrong with them, I just never got into them). -
Any chance to see NNTP version of the forum?
Remy Lebeau replied to AlexBelo's topic in Community Management
Very carefully! -
Conditional compilation for various Delphi versions
Remy Lebeau replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Actually, since Delphi 6+, the preferred method is to use $IF with the CompilerVersion and/or RTLVersion constants, instead of using $IFDEF with the VERxxx conditionals. -
What is the fastest way to check if a file exists?
Remy Lebeau replied to dummzeuch's topic in Windows API
Why is GetFileAttributes the way old-timers test file existence? -
And even that is not needed if you use CreateProcessElevated() instead.
-
Your TIdHTTP code is all wrong for this kind of POST request. Try something more like this instead: uses ..., IdGlobalProtocols, IdHTTP, IdSSLOpenSSL; procedure TForm3.Button2Click(Sender: TObject); var SoapMsg: string; PostData, ResponseData: TStream; begin // buid up this string however you want (XML library, etc) ... SoapMsg := '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">' + ' <soapenv:Header/>' + ' <soapenv:Body>' + ' <tem:Consulta>' + ' <!--Optional:-->' + ' <tem:expresionImpresa><![CDATA[?re=LSO1306189R5&rr=GACJ940911ASA&tt=4999.99&id=e7df3047-f8de-425d-b469-37abe5b4dabb]]></tem:expresionImpresa>' + ' </tem:Consulta>' + ' </soapenv:Body>' + '</soapenv:Envelope>'; ResponseData := TMemoryStream.Create; try PostData := TStringStream.Create(SoapMsg, TEncoding.UTF8); try IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1; IdHTTP1.HTTPOptions := IdHTTP1.HTTPOptions + [hoNoProtocolErrorException, hoWantProtocolErrorContent]; IdHTTP1.Request.ContentType := 'text/xml'; IdHTTP1.Request.Charset := 'utf-8'; IdHTTP1.Request.Accept := 'text/xml'; IdHTTP1.Request.CacheControl := 'no-cache'; IdHTTP1.Request.CustomHeaders.Values['SOAPAction'] := 'http://tempuri.org/IConsultaCFDIService/Consulta'; IdHTTP1.Post('https://consultaqr.facturaelectronica.sat.gob.mx/ConsultaCFDIService.svc?wsdl', PostData, ResponseData); finally PostData.Free; end; Memo1.Lines.BeginUpdate; try Memo1.Lines.Add(Format('Response Code: %d', [IdHTTP1.ResponseCode])); Memo1.Lines.Add(Format('Response Text: %s', [IdHTTP1.ResponseText])); ResponseData.Position := 0; ReadStringsAsCharset(ResponseData, Memo1.Lines, IdHTTP1.Response.Charset); finally Memo1.Lines.EndUpdate; end; finally ResponseData.Free; end; end;
-
How to obtain the value of a field of type TWndMethod via RTTI?
Remy Lebeau replied to Kryvich's topic in RTL and Delphi Object Pascal
Remember that a pointer-to-class-method, such as TWndMethod, is represented by the RTL's TMethod record, which contains 2 pointers - a pointer to an object instance, and a pointer to the method code. TValue.AsUInt64 fails for a TWndMethod value because TValue supports only conversions that the compiler natively supports implicitly, and you can't implicitly assign a TMethod to a UInt64 and vice versa. That also explains why the TValue.GetReferenceToRawData() approach works - it is just returning a raw pointer to the actual TControl.FWndMethod instance member, which is then dereferenced when being assigned to the local TWndMethod variable. So, no conversion occurs. Now, why TValue.AsType<TWndMethod> fails to compile, I don't know. Sounds like a bug. -
VCL Support for Per Monitor v2 and GetSystemMetrics Coming in 10.3
Remy Lebeau replied to Marco Cantu's topic in VCL
The VCL has a GetParentForm() function in the Vcl.Forms unit for this very purpose. -
appending to a dynamic array
Remy Lebeau replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
I would probably take it a step further, to avoid repeatedly indexing into the array: var Idx: integer; Rec: ^TSomeRec; // [...] Idx := CountInMyArr; SetLength(MyArr, Idx + SomeDelta); Rec := @MyArr[Idx]; Rec.SomeField := SomeValue; // and repeated for each field in TSomeRec Inc(CountInMyArr);