1

As a newbie in Delphi I run into a problem with an external API. This external API expects a parameter with one or two value, I think called bitwise parameter. In Delphi this is done by a set of

The basic is an Enumeration.

TCreateImageTask = (
  citCreate = 1,
  citVerify
);

This I have put into a set of:

TCreateImageTasks = set of TCreateImageTask

In a function I fill this set with:

function TfrmMain.GetImageTask: TCreateImageTasks;
begin
    Result:=[];
    if chkCreate.checked then Include(Result, citCreate);
    if chkVerify.checked then Include(Result, citVerify);
end;

Now I have to give this Tasks to a external DLL, written in C++ The DLL expects a __int8 value. It may contain one or two TCreateImageTasks. In C++ done by:

__int8 dwOperation = 0;

   if (this->IsDlgButtonChecked(IDC_CHECK_CREATE))
   {
      dwOperation = BS_IMGTASK_CREATE;
   }

   if (this->IsDlgButtonChecked(IDC_CHECK_VERIFY))
   {
      dwOperation |= BS_IMGTASK_VERIFY;
   }

int32 res = ::CreateImage(cCreateImageParams, dwOperation);

So I have to convert my set of to an integer. I do by

function TfrmMain.SetToInt(const aSet;const Size:integer):integer;
begin
  Result := 0;
  Move(aSet, Result, Size);
end;

I call with

current task := GetImageTask;
myvar := SetToInt(currentTask, SizeOf(currentTask));

The problem I have now, that myvar is 6 when 2 values are inside the set, 2 if only create is inside the set and 4 if only verify is inside the set. That do not look right to me and the external DLL do not know this values.

Where is my fault?

ingo
  • 776
  • 1
  • 10
  • 25
  • 3
    You don't seem to know what "flags" are and how a byte can combine 8 bits: `2 or 4` makes `iValue= 6` and any code is still able to test against `if iValue and 2<> 0 then` . Creating an ENUM is wrong and seems to be entirely your idea, not the one of the API. – AmigoJack Jun 29 '19 at 08:09
  • Sorry, the enum is out of the API. So there is still the question why the Enum citCreate is 1 but after put into an integer Is 2. I also think this is nothing about flags, because I also testes with a naked simple Delphi form without any special setting, just defaults. – ingo Jun 29 '19 at 08:57

2 Answers2

2

I guess it works when you remove the = 1 in the declaration of TCreateImageTask?

The = 1 shifts the ordinal values by 1 giving the results you see, but is probably not what is needed. For that we need to know the values for BS_IMGTASK_CREATE and BS_IMGTASK_VERIFY.

My psychic powers tell me that BS_IMGTASK_CREATE = 1 and BS_IMGTASK_VERIFY = 2. Given that these are bit masks they correspond to the values 2^0 and 2^1. This matches the ordinal values 0 and 1.

Thus you should declare

TCreateImageTask = (citCreate, citVerify);

to map citCreate to 0 and citVerify to 1.

Uwe Raabe
  • 45,288
  • 3
  • 82
  • 130
0

It's all about something called Bitwise Operation!

Converting a SET to LONGWORD is widely used in Delphi implementation of Windows API.

This would be what you are looking for:

How to save/load Set of Types?

This was already answered here too:

Bitwise flags in Delphi

Luiz Vaz
  • 1,669
  • 1
  • 19
  • 32