How to use threads in lazarus? - multithreading

I'm developping a multithread application using Lazarus. As i know, i have to add the class "cthreads" to uses clause, and define it in "ifdef usesCthreads", so here is the relevant part of the code:
unit Unit2;
{$mode objfpc}{$H+}
{$IFDEF usesCthreads}
Cthreads;
{$ENDIF}
interface
uses Forms, Classes, SysUtils, SyncObjs, Math, IdHttp,DateUtils,Dialogs,
ComCtrls, IdHashMessageDigest,idHash,IdComponent, cthreads;
There was no compilation error, but the form is not created because I'm having this message right after compilation: 'Run Error(211)' , plus the assembly window is showing: Cthreads_init(127).
I guess something is wrong with my code, so what is it?
Thanks for your replies.

Related

Problem handling threads within a DLL in Delphi

I'm testing out the QuickLogger library from Exilon, which I found to be a pretty versatile logging library, and later on found that it can be accessed through the GetIt Package Manager.
I have been struggling to encapsulate logging abilities for our win32 apps, but only when they are executed on Windows 7 or Windows Server 2008 R2. If I run the code on Windows 10 or Windows Server 2016 or 2019, it works like a charm.
The problem seems to be related to thread handling inside a DLL.
I isolated the problem to the bare minimum code.
The library
library libProject;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
//ShareMem,
System.SysUtils,
System.Classes,
Quick.Logger,
Quick.Logger.Provider.Console;
{$R *.res}
function AddIntegers(const _a, _b: integer): integer; stdcall;
begin
Result := _a + _b;
Logger.Debug('Some debug info');
end;
exports
AddIntegers;
begin
Logger.Providers.Add(GlobalLogConsoleProvider);
with GlobalLogConsoleProvider do
begin
LogLevel := LOG_VERBOSE;
ShowEventColors := True;
Enabled := True;
end;
end.
The test program
program consoleProject;
{$APPTYPE CONSOLE}
{$R *.res}
uses
//ShareMem,
System.SysUtils,
Quick.Logger,
Quick.Logger.Provider.Console;
function AddIntegers(_a, _b: integer): integer; stdcall; external 'libProject.dll';
begin
Logger.Providers.Add(GlobalLogConsoleProvider);
try
WriteLn(AddIntegers(1, 2));
WriteLn('Press Enter');
ReadLn;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
end.
Basically, the problem is that the DLL prevents the app from terminating normally because of some unfinished thread execution.

Why do I need Sharemem in my Delphi dll which only exposes a function with WideString parameters?

I have a dll and a test application written in Delphi. The test application uses multiple threads to call the function exported by the dll. The exported function has a trivial thread safe implementation. When running the test application various errors (access violation, invalid pointer operation, stack overflow etc) happens or the application freezes. In some cases the application finishes without errors.
Note that these errors only happen (surface) when using multiple threads. When calling the function from the main thread only then everything works fine.
I have found that adding ShareMem to both the dll and the application stops all these kind of errors. But I don't understand why. To my knowledge ShareMem is only needed when passing long strings between the dll and the application. As far as I know WideString is not a long string.
Also according to this post ShareMem should not be required:
Why can Delphi DLLs use WideString without using ShareMem?
Here is the source of the dll:
library External;
uses
Winapi.Windows;
type
TMyType = class
private
FText: string;
end;
function DoSomething(input: WideString; out output: WideString): Bool; stdcall;
var
x: TObject;
begin
x := TMyType.Create;
try
output := x.ClassName;
finally
x.Free;
end;
Result := True;
end;
exports
DoSomething;
begin
end.
Here is the test application:
program ConsoleTest;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
Winapi.Windows,
OtlParallel;
function DoSomething(input: WideString; out output: WideString): Bool; stdcall; external 'External.dll' name 'DoSomething';
var
sResult: WideString;
begin
try
Parallel.&For(0, 500).Execute(procedure(value: Integer)
var
sResult: WideString;
begin
DoSomething('hhh', sResult);
end);
WriteLn('Done');
ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Why ShareMem makes the bugs go away and is there another way to fix these bugs?
I am using Delphi XE2 and OmniThread 3.07.5.
Update
- Same issue when run from a VCL application's button's on click event handler
- If DoSomething uses a critical section inside then runs fine
- If FText field is removed from TMyClass then no errors are reported but the application randomly freezes
For the standard memory manager (FastMM) to support multi threading, you need to set the IsMultiThread flag.
When you use RTL for threading, this flag is automatically set. As revealed in the comments to the question, OTL also use RTL to start its threads. So the memory manager in your executable is aware of threading, but the distinct memory manager in the dll causes errors. When you use "sharemem", there is only one memory manager which is aware of threading because of OTL, so you encounter no errors.
An alternative solution, apart from using a shared memory manager, would be to set the flag also for the memory manager in the dll.

Setup Programs created using Inno Setup Compiler doesn't display Minimize Animation

My Problem is why Inno Setup Compiler (Unicode or ANSI) and any Setups made by it don't minimize showing a nice Minimizing Animation like in Other Windows Programs?
It displays a very basic Minimize Animation..........Why that?
I know Borland Delphi as Inno Setup Compiler's Compiler, but Borland Delphi doesn't have such a bad Minimize Animation...........It minimizes normally as Windows System Windows minimize (such as Explorer, Computer, Control Panel).................
I also noticed that the Windows Installer Creater Nullsoft Scriptable Install System - NSIS and Setups made using it are also minimizing well like I said.
How can I resolve this problem?
UPDATED QUESTION
I also added a code to play that nice Zooming Minimize / Restore Animation can be seen in Many Windows Applications on Inno Setup's WizardForm, But when I click the WizardForm's Minimize Button after adding this code to Inno Setup Compiler's Source Code, the Nice Zooming animation not plays and it never can be minimized using it, it only can be minimized using Taskbar button after adding this code. So it means this code not working or anything else wrong...........Why this is not working???
The Code I Added to unit WizardForm:
interface
uses
Windows;
type
TTrayZoom = class(TObject)
private
class function GetTrayRect: TRect;
class procedure DoZoom(const Wnd: HWND; const Src, Dest: TRect);
public
class procedure ZoomToTray(const Wnd: HWND);
class procedure ZoomFromTray(const Wnd: HWND);
end;
implementation
class procedure TTrayZoom.DoZoom(const Wnd: HWND; const Src, Dest: TRect);
begin
DrawAnimatedRects(Wnd, IDANI_CAPTION, Src, Dest);
end;
class function TTrayZoom.GetTrayRect: TRect;
var
TaskbarWnd, TrayWnd: HWND;
begin
TaskbarWnd := FindWindow('Shell_TrayWnd', nil);
TrayWnd := FindWindowEx(TaskbarWnd, 0, 'TrayNotifyWnd', nil);
GetWindowRect(TrayWnd, Result);
end;
class procedure TTrayZoom.ZoomFromTray(const Wnd: HWND);
var
WndRect: TRect;
begin
GetWindowRect(Wnd, WndRect);
DoZoom(Wnd, GetTrayRect, WndRect);
end;
class procedure TTrayZoom.ZoomToTray(const Wnd: HWND);
var
WndRect: TRect;
begin
GetWindowRect(Wnd, WndRect);
DoZoom(Wnd, WndRect, GetTrayRect);
end;
And I called TTrayZoom.ZoomToTray from if WMSysCommand..... = SCMINIMIZE and called TTrayZoom.ZoomFromTray from if WMSysCommand..... = SCRESTORE with the setting HWND parameter to WizardForm.Handle.
But those codes never works, I even don't know if they're get called or not. :(
What is the problem playing this Zooming Animation in this WizardForm?
I'd say there are two issues.
The animation is shown for windows that have a task bar button. The wizard form does not have a task bar button.
The task bar button of the installer belongs to a hidden main window.
Historically the installers had full screen background gradient blue windows. Even Inno Setup supported that.
While that background window is no longer enabled by default (the WindowVisible directive defaults to No in modern versions of Inno Setup), it still exists and owns the task bar button.
Inno Setup is built using an ancient version of Delphi that likely does not play nicely with the minimize feature.
Generally, I'd say you should file a feature request/bug report to get this fixed.

Delphi pass string to procedure gets an access violation error

I am currently trying to create a test procedure and pass it a string. And the function checks the string for equivalence. The problem is that when the test runs, I get a access violation error of EAccessViolation on the string that I pass inside the Procedure. I understand that this is a memory declaration problem but I am not sure how to fix it.
Here is my code:
Declare
TestTForm1 = class(TTestCase)
strict private
FForm1: TForm1;
public
procedure SetUp; override;
procedure TearDown; override;
published
procedure TestCompareListBoxToFile(Method : String);
end;
Call
TestCompareListBoxToFile('Save');
Procedure
procedure TestTForm1.TestCompareListBoxToFile(Method : String);
begin
Check('Save' = Method,'they dont match');
end;
I am new to delphi so if there is anything I am missing, please let me know. please be specific in the response. Thank you.
That code is called by the unit test runner. It uses RTTI to find published methods whose names begin with 'Test'. On the face of it, this appears to be a DUnit test case.
The runner expects a procedure that accepts no parameters, and calls the method as such. You on the other hand, provide a method that does require a parameter. A parameter that is not provided. Hence the runtime error.
Now, somewhere in your code you say that you are calling the method like this:
TestCompareListBoxToFile('Save');
But that's just not how tests are invoked. Tests are invoked by the runner which uses RTTI to do so. If you attempt to call the function as well, that's just wrong.
You must declare your method like this:
procedure TestCompareListBoxToFile;
You probably need to go back to the documentation and examples for the unit test framework and learn how to design your test case to be able to accept parameters. In fact, before even doing that, I suggest you go right back to basics and make sure you fully understand how the runner discovers your tests and then runs them.

Lazarus resource - Using a resource leads to an error in linking

I searched around but found not any solution, so I try here:
I want to integrate images (I did it with delphi before in this way) that are used by my program and load them at runtime.
My idea was to
1.) create a resource file with
lazres <resourcename> <imagename>
2.) include the resource file in the source
{$R <resourcename>}
3.) compile
Result:
Unable to find file "Debug: Trying to open file /medi/media/work/src.hg/ylazlib/test/test.src/libtest6.lpr".
The filename above is the project source and should be found.
I found out that this error almost alwas results from invalid resource files.
But the message should be explaining the problem in a better manner.
If I rename the resource file ( so it can not be found by linker) I get a 'correct' error message. In this case the unit that requires the resource is opened and the message states that the resource file can not be opened.
So what am I doing wrong here?
(I also tried to insert images in different format to the resource - so the image itself may not the problem)
any help apreciated - Thanks in advance
Note: OS: debian sid [fpc 2.6.4] Lazarus SVN
The procedure to follow is a bit different than in Delphi. As explained here, you have to
add LResources to the uses clause.
include the res file produced by Lazres in the initialization section.
uses {$I myRes} rather than {$R myRes}.
a quick test with
console lzares cmd:
C:\Users\me\Desktop\temp>lazres res.res project1.lpr=blah
source code:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,LResources;
type
TForm1 = class(TForm)
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
initialization
{$I res.res}
end.
compiles and runs fine. Then later this can be a bit tricky to load the res if they are raw data but for pictures it's quite straightforward, cf the example in the previous link.

Resources