Код Delphi DX10.4 E2064 не компилируется

#delphi

#delphi

Вопрос:

Я не очень хороший программист на Delphi, я рад программировать на C Builder, delphi — не мой язык. У меня есть некоторые компоненты, написанные на Delphi, и они отлично компилируются в 10.3, но я получаю ошибки в 10.4, и я вижу причину проблемы, но я понятия не имею, как это исправить. Пожалуйста, помогите мне это исправить.

 procedure CopyInterlacedRGB8(const Pass: Byte; Src, Dest, Trans, Extra: pChar)

    Dest^ := Char(fOwner.GammaTable[pByte(Longint(Src)   2)^]); inc(Dest);  // changed these two, but I have no clue what I'm doing lul
    Dest^ := Char(fOwner.GammaTable[pByte(Longint(Src)   1)^]); inc(Dest);
    Byte(Dest^) := fOwner.GammaTable[pByte(Longint(Src)    )^]; inc(Dest);  // ERROR here
  

Как я вижу здесь, насколько я понимаю в C , инициализируется байт, и он присваивается. Аналогично char(‘a’) = 5; Но я могу видеть, что код изначально хочет сделать, назначить что-то адресу Dest.

Как я должен изменить этот материал, чтобы он работал??

Комментарии:

1. Какие ошибки вы получаете?

2. Вы забыли сообщить нам, какую ошибку вы получили. Тем не менее, Dest это PChar , поэтому Dest^ это Char . Это двухбайтовое значение, поэтому вы не можете преобразовать его в Byte .

3. Если вы не имеете дело с 16 / 48bit RGB, все эти переменные просто хотят иметь дело с байтами, а не со словами. Используйте PAnsiChar вместо PChar — имя вашей функции в любом случае указывает на 8 бит.

4. Этот код в любом случае выглядит дефектным, даже если вы можете заставить его скомпилироваться. Char имеет ширину в два байта в обеих версиях, на которые вы ссылаетесь. Вы, вероятно, захотите не только скомпилировать код, но и заставить его работать!

5. @AmigoJack OP манипулирует данными в байтах RGB. Они не должны использовать Char или PAnsiChar — это строковые типы для символов и текста. Byte и TBytes было бы подходящим. Нет разумного решения с pChar в качестве аргумента, поэтому принципиально этот метод никогда не может быть полезным. Способ разработки замены для него будет зависеть от контекста, в котором вы работаете. Первым шагом должен быть выбор подходящего типа аргумента.

Ответ №1:

Вы не дали объявление GammaTable . Я создал тот, который кажется подходящим. Я не инициализировал его здесь, но он должен быть в вашем коде. Если ваше объявление отличается, возможно, мой код должен быть изменен.

 var
    GammaTable : array [Byte] of Byte;

procedure CopyInterlacedRGB8(const Pass: Byte; Src, Dest, Trans, Extra: pChar);
var
    BDest : PByte;
begin
    BDest  := PByte(Dest);
    BDest^ := GammaTable[PByte(UIntPtr(Src)   2)^]; Inc(BDest);
    BDest^ := GammaTable[PByte(UIntPtr(Src)   1)^]; Inc(BDest);
    BDest^ := GammaTable[PByte(UIntPtr(Src)    )^]; Inc(BDest);
end;
  

Я не изменил тип аргументов в функции, но наверняка Src и Dst должно быть PByte не PChar . В любом случае, написанный мной код будет работать одинаково хорошо, каким бы он ни был, при условии, что он содержит желаемую исходную и целевую таблицы.

Я ввел BDest переменную, чтобы сделать код более читаемым.

Обратите внимание, что если Src объявлено как PByte и {$POINTERMATH ON} , то код может быть упрощен:

PByte(UIntPtr(Src) 2)^

становится

Src[2];

Таким образом, процедура может быть переписана следующим образом:

 {$POINTERMATH ON}
procedure CopyInterlacedRGB8_(const Pass: Byte; Src, Dest : PByte; Trans, Extra: pChar);
begin
    Dest[0] := GammaTable[Src[2]];
    Dest[1] := GammaTable[Src[1]];
    Dest[2] := GammaTable[Src[0]];
end;
  

Гораздо более читабельный, не так ли?

Комментарии:

1. PByte объявляется с {$POINTERMATH ON} уже включенным на нем, поэтому вам не нужно вручную включать математику указателей в вашем собственном коде, чтобы использовать математику указателей для PByte переменной.

2. @RemyLebeau Полезно знать!

3. Я бы, вероятно, просто сбросил ненужные параметры Trans и Extra — по крайней мере, для этого примера они совершенно бессмысленны. OP не показал нам никакого кода, который требует их.