Lazarus 1.6, обсудим изменения...
Модератор: Модераторы
У меня тоже проблемка с set. Точнее с sizeOf(T), где T = set of ...
Раньше sizeOf(T) равнялся 4, теперь 1. И директива {$MINENUMSIZE 4} ситуацию не исправляет. Никто не подскажет как быть?
Хотя бы как в коде понять версию fpc, чтобы дифференцировать объявление packed record в котором стоит тип T?
Раньше sizeOf(T) равнялся 4, теперь 1. И директива {$MINENUMSIZE 4} ситуацию не исправляет. Никто не подскажет как быть?
Хотя бы как в коде понять версию fpc, чтобы дифференцировать объявление packed record в котором стоит тип T?
http://wiki.freepascal.org/User_Changes_2.6.0
подозреваю надо {$packset 4}
Sizes of sets in TP/Delphi mode
Old behaviour: {$packset fixed} was the default for all language modes. This packs a set of up to 32 elements in 4 bytes, and all other sets in 32 bytes.
New behaviour: The default in TP/Delphi mode is now {$packset 1}
Effect: In those language modes the size of sets with 1..8 elements will now be 1 byte, and the size of sets with 9..16 elements will be two bytes. Sets with 17..32 elements will remain 4 bytes, but after that every additional 8 elements the size will increase by 1 byte up to 249..256 elements, which will result in a set of 32 bytes.
Reason: TP/Delphi compatibility.
Remedy: If you have code written in TP/Delphi mode that depends on the old packset setting, add {$packset fixed} to the source (after setting the syntax mode to Delphi/TP, since the mode switching changes the packset setting). This is backward compatible with at least FPC 2.2.4 and later.
подозреваю надо {$packset 4}
sts
Спасибо, действительно не ту директиву ставил.
Спасибо, действительно не ту директиву ставил.
-
Aleksey Elin
- новенький
- Сообщения: 15
- Зарегистрирован: 13.09.2012 22:34:34
Не могу понять логику работы строковых констант в новом FPC при использовании UnicodeString (или WideString).
При ПРЯМОМ присваивании переменной или вызове процедуры/функции/метода с параметром UnicodeString происходит непонятное преобразование символов.
Если же присваивать переменной UnicodeString значение переменной обычной строки string то все ок., при том что и в константе и в строке string хранятся одни и те же utf8 символы,
см. кусок кода ниже:
Подозреваю что в константе cc неверно задана кодировка, но почему тогда при работе через промежуточную переменную t все ок?
И что делать, учитывая что у меня тонны унаследованного кода с использованием UnicodeString и вызовами методов с константами/непосредственно заданными значениями!?
PS: Если добавить к .pas модулю префикс utf8 то константа сс неожиданно становится 10-символной с 2-х байтными символами (судя по кодам символов - utf16)!!! что вообще взрывает мой мозг.
При ПРЯМОМ присваивании переменной или вызове процедуры/функции/метода с параметром UnicodeString происходит непонятное преобразование символов.
Если же присваивать переменной UnicodeString значение переменной обычной строки string то все ок., при том что и в константе и в строке string хранятся одни и те же utf8 символы,
см. кусок кода ниже:
Код: Выделить всё
procedure LogClear; forward;
procedure Log(const S : UnicodeString); forward;
function cvt(const s : string) : string;
begin
Result:=s
end;
const
cc = 'Привет мир';
procedure TForm1.Button1Click(Sender: TObject);
var
t : string;
s : UnicodeString;
i, n : Integer;
begin
LogClear;
t:=cc;
i:=SizeOf(t[1]); n:=SizeOf(cc[1]);
Log( IntToStr(i)+', '+IntToStr(n) ); // вывод 1, 1 -> обе строки t и cc однобайтные
Log( IntToStr(Length(t)) ); // длина 19 байт -> все ок, t - строка utf8
Log( IntToStr(Length(cc)) ); // длина 19 байт -> все ок, cc - строковая константа utf8
n:=0; i:=1;
while (i<=Length(t)) and (i<=Length(cc)) do begin
if t[i]=cc[i] then Inc(n);
Inc(i);
end;
Log( IntToStr(n) ); // число совпадающих байт 19 - строки побайтно равны
Log( t ); // выводится правильная строка
Log( cc ); // выводятся крякозыбры!!! несмотря на то что cc ничем не отличается от t!
s:=cc; Log( s ); // выводятся крякозыбры
s:=t; Log( s ); // выводится правильная строка
Log( SysToUTF8(cc) ); // выводится правильная строка
Log( cvt(cc) ); // выводится правильная строка
Log( string(cc) ); // неожиданно опять выводятся крякозыбры!!!
Log( 'Привет мир' ); // те же самые крякозябры...
end; Подозреваю что в константе cc неверно задана кодировка, но почему тогда при работе через промежуточную переменную t все ок?
И что делать, учитывая что у меня тонны унаследованного кода с использованием UnicodeString и вызовами методов с константами/непосредственно заданными значениями!?
PS: Если добавить к .pas модулю префикс utf8 то константа сс неожиданно становится 10-символной с 2-х байтными символами (судя по кодам символов - utf16)!!! что вообще взрывает мой мозг.
Aleksey Elin писал(а):Подозреваю что в константе cc неверно задана кодировка
Кодировка константы = кодировке страницы.
Кодировка страницы - см.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
-
Aleksey Elin
- новенький
- Сообщения: 15
- Зарегистрирован: 13.09.2012 22:34:34
sign писал(а):Aleksey Elin писал(а):Подозреваю что в константе cc неверно задана кодировка
Кодировка константы = кодировке страницы.
Кодировка страницы - см.
У меня именно так и есть - кодировка страницы utf8.
Собственно я об этом и писал - видно что в константе хранятся именно utf8 символы, но при присваивании переменной UnicodeString происходит неверное преобразование неизвестно во что.
Код: Выделить всё
const
cc = 'Привет мир';
----------------------------
var
t : string;
s : UncodeString;
----------------------------
s:=cc; // не работает
s:='Привет мир'; // не работает
s:=string('Привет мир'); // не работает
s:=string(cc); // не работает
t:=cc; s:=t; // работает, причем t и сс побайтно равны и там лежат utf8 символы
Добавлено спустя 2 часа 32 минуты 38 секунд:
Немного разобрался что происходит с константами.
Компилятор FPC для каждой строковой константы создает два представления в области констант: в однобайтовой кодировке (CP_ACP=0 или CP_UTF8 в зависимости от BOM см.ниже) и в двухбайтовой кодировке (СP_UTF16=1200), и использует одну из них по обстоятельствам.
При работе с однобайтными строками (string) все ок: происходит копирование строки без всяких изменений из исходного файла, и если исходный файл в utf8 кодировке - лазарус воспринимает их как родные... (однако не будет работать ни с какой другой кодировкой исходного файла, например с cp1251, потребуется ручная перекодировка констант в строки utf8).
При работе с двухбайтными строками (UnicodeString/WideString) есть 2 варианта:
1. Исходный .pas файл содержит UTF8 BOM префикс (Byte Order Mark = [$EF,$BB,$BF]), в этом случае для создания двухбайтных констант компилятор конвертирует строку из исходного файла из кодировки utf8 в кодировку utf16. И при использовании UnicodeString все ок.
2. Исходный файл не содержит префикса, и тогда для создания двухбайтных констант компилятор просто переносит каждый байт строки из файла в WideChar константы двухбайтной кодировки, что неверно для символов с кодами >=128 (т.е. для любых символов не входящих в ASCII).
Таким образом при использовании локализованных строковых констант требуется, чтобы исходный файл был не только в кодировке utf8, но и содержал UTF8 BOM префикс! Это не будет критично при использовании только однобайтных строк (string), но приведет к прблемам при использовании таких констант с переменными UnicodeString/WideString или параметрами процедур/функций/методов с этими типами. Это касается и непосредственно заданных констант без предварительного объявления, например: S:='Строка'; или Foo('Строка');
Возможно имеется опция компилятора, позволяющая принудительно указать кодировку для файлов без префиксов для корректного формирования строковых констант, может кто подскажет?
Последний раз редактировалось Aleksey Elin 05.04.2016 16:46:00, всего редактировалось 1 раз.
Aleksey Elin писал(а):Возможно имеется опция компилятора, позволяющая принудительно указать кодировку для файлов без префиксов для корректного формирования строковых констант, может кто подскажет?
Попробуйте http://www.freepascal.org/docs-html/prog/progsu88.html
Код: Выделить всё
{$codepage utf8}-
Aleksey Elin
- новенький
- Сообщения: 15
- Зарегистрирован: 13.09.2012 22:34:34
Нашел ответ на последний вопрос в freepascal wiki:
http://wiki.freepascal.org/LCL_Unicode_Support/ru#.D0.9A.D0.BE.D0.B4.D0.BE.D0.B2.D1.8B.D0.B5_.D1.81.D1.82.D1.80.D0.B0.D0.BD.D0.B8.D1.86.D1.8B_FPC
Там же и некоторые подробности и подводные камни. Несмотря на то, что статья про FPC 2.7.1 в FPC 3.0.0 проблемы те же.
И спасибо bormant, действительно {$codepage utf8} работает точно так же как UTF8 BOM, но последний вариант мне субъективно больше нравится.
http://wiki.freepascal.org/LCL_Unicode_Support/ru#.D0.9A.D0.BE.D0.B4.D0.BE.D0.B2.D1.8B.D0.B5_.D1.81.D1.82.D1.80.D0.B0.D0.BD.D0.B8.D1.86.D1.8B_FPC
Там же и некоторые подробности и подводные камни. Несмотря на то, что статья про FPC 2.7.1 в FPC 3.0.0 проблемы те же.
И спасибо bormant, действительно {$codepage utf8} работает точно так же как UTF8 BOM, но последний вариант мне субъективно больше нравится.
Aleksey Elin писал(а):но последний вариант мне субъективно больше нравится
не вам одному. По крайней мере он явно виден глазами, в отличии от BOM.
Aleksey Elin писал(а):Нашел ответ
А что ж не нашли вторую часть ответа?: http://wiki.freepascal.org/Better_Unico ... Lazarus/ru
-
Aleksey Elin
- новенький
- Сообщения: 15
- Зарегистрирован: 13.09.2012 22:34:34
SSerge Я не очень понял что вы имели ввиду насчет второй части?
resident писал(а):А вот чего дальше и не знаю, можно конечно подключить файл LazUTF8, но там же функции пустышки.
(Файловые функции теперь в файле LazFileUtils.)
Спасибо за подробное объяснение. Оказывается, здесь нет автоматической подписки на тему, поэтому думал, что вопрос остался без ответа.
Я решил проблему заменой функций UTF8ToSys и SysToUTF8 на UTF8ToWinCP и WinCPToUTF8 соответственно. Хотя, после доработки функций работы со строками в Lazarus 1.6 пришлось в своём коде часть вызовов этих функций убрать, так как функциональность по конвертации строк уже включена в другие функции. Но, увы, не во все, поэтому постоянно приходится держать руку на пульсе и следить за кодировкой.
Может уже обсуждалось, но я не следил за 1.6 до релиза финального.
Наткнулся на проблему. При выполнении
Стабильно вылетает ошибка на строке 530 модуля Themes, если в списке требуемых пакетов открываемой библиотеки есть LazControls.
До этого все собиралось нормально.
Наткнулся на проблему. При выполнении
Код: Выделить всё
DLLHandle := loadLibrary (PluginPath);
Стабильно вылетает ошибка на строке 530 модуля Themes, если в списке требуемых пакетов открываемой библиотеки есть LazControls.
До этого все собиралось нормально.
Код: Выделить всё
//Themes.pas
function ThemeServices: TThemeServices;
begin
Result := WidgetSet.ThemeServices; //530 line
end;
Ошибка то какая?
Возможно следы прошлых компиляций - почистить все папки lib и проекта и пакетов.
Но скорее всего последствия "обдлливания" "необдлливаемого"((
Возможно следы прошлых компиляций - почистить все папки lib и проекта и пакетов.
Но скорее всего последствия "обдлливания" "необдлливаемого"((
zub писал(а):Ошибка то какая?
Возможно следы прошлых компиляций - почистить все папки lib и проекта и пакетов.
Но скорее всего последствия "обдлливания" "необдлливаемого"((
Чистил все. Две одинаковые dll одна с пакетом LazControl, другая без. На новой версии работает только вторая.
Ошибка без словесного описания, там адрес и все.
Я проблему нашел и устранил для себя(LazControl долой), но вообще удивило, что программа стопорится и функция loadlibrary уже больше ничего не возвращает. Когда начинал с ней работать кривые dll ей давал и она их ела, без проблем, просто не возвращала идентификатор. А тут вообще полное падение.
