Про gcc и кодировки

Задача
Есть AVR и желание выводить с его помощью русские строки.Есть gcc в качестве компилятора, работающий под виндой.
Нет желания городить свою библиотеку для работы с utf-8.
Спрашивается: как?
Сначала я сделал как в VC++: открыл любимый блокнотик, забил туда win-1251, сама строка была задана вот так:
char s[] = {"Тестовая строка"};
Собрал, запустил… мимо.
Ок, пошёл в гугл.
Нашёл страничку.
Поставил опциями компилятора win-1251 на входе и выходе.
Всё сломалось с криком:
"cc1plus.exe: error: no iconv implementation, cannot convert from win-1251 to UTF-8".
Ну, примерно с таким криком.
Дальше я долго гуглил, выяснил таки, что проблема в том, что в винде нет волшебного iconv (libiconv), который есть в линуксе, и что эта самая либа должна быть статически влинкована в gcc.
Нашёл адский тредик, как мужики пытались это сделать.
И наконец таки нашёл страничку с уже готовым gcc.
Ура. Скачал. Обновил.
Дальше просто. Сначала нужно взять свои исходники и сконвертить их в utf-8. На всякий случай. Может и без этого заработает.
Потом поправить строчку с ключиками от gcc:
C:\tools\avr-gcc\bin\avr-g++.exe -mmcu=atmega8515 -finput-charset=UTF-8 -fexec-charset=cp1251 -std=gnu++11 -Os main.cpp -o main.o
Потом запустить сборку, и вдумчиво посмотреть в полученный бинарник.
Дальше открываем .hex файл и убеждаемся, что в нём появились вполне нормальные ASCII коды, которые похожи на строку в win-1251!
Profit!
ЗЫ: Да, найденная сборка gcc имеет одну неприятную особенность: внутри она содержит неправильный avr-size, который не понимает ключик mmcu.
- +1
- 10 февраля 2016, 12:03
- JustMoose
А ещё лучше не сувать русских строк в код, а пихать их отдельным файлом и вставлять define'ом
А самый верх навыка джедая — делать массив строковых констант и заполнять его из файла линковщиком. Но это сложно. Зато позволяет не только русский текст, но и картинки bmp, файлы wav и прочие ресурсы пихать.
А самый верх навыка джедая — делать массив строковых констант и заполнять его из файла линковщиком. Но это сложно. Зато позволяет не только русский текст, но и картинки bmp, файлы wav и прочие ресурсы пихать.
Мне кажется, что вставить что-либо из внешнего файла можно include-ом. А не define-ом.
Кроме того, препроцессор (обрабатывающий include/define/etc) работает до компилятора. А значит компилятору всё равно придётся как-то рассказать, какая у входного файла кодировка.
Про линковщик. Я не знаю способа, как заставить AVR/gcc прочитать чего-нибудь из бинаря. Ну, кроме функции pgm_read_byte. Но этой функции надо дать адрес. А адресами ведает компилятор, а не линковщик. (Ну, точнее сказать, узнать адрес проще с помощью компилятора, а не линковщика).
Вообще, массивы строк, битмапки и т.п. действительно стоит хранить как-то отдельно. Но это лучше делать под полноценной ОСью, которая умеет что-то читать из биинарника (например, в винде есть набор функций, которые читают из ресурсов иконки/строки), плюс, это стоит делать для сравнительно больших проектов, которые требуют специфики: например, если надо сделать локализацию приложения, то можно действительно подключить разные ресурсы с разными строками.
У меня же есть мелкий микроконтроллер и прошивка. ОСи нет. Ресурсов нет. Функций чтения из файлов нет. Нет даже файловой системы :)
Кроме того, препроцессор (обрабатывающий include/define/etc) работает до компилятора. А значит компилятору всё равно придётся как-то рассказать, какая у входного файла кодировка.
Про линковщик. Я не знаю способа, как заставить AVR/gcc прочитать чего-нибудь из бинаря. Ну, кроме функции pgm_read_byte. Но этой функции надо дать адрес. А адресами ведает компилятор, а не линковщик. (Ну, точнее сказать, узнать адрес проще с помощью компилятора, а не линковщика).
Вообще, массивы строк, битмапки и т.п. действительно стоит хранить как-то отдельно. Но это лучше делать под полноценной ОСью, которая умеет что-то читать из биинарника (например, в винде есть набор функций, которые читают из ресурсов иконки/строки), плюс, это стоит делать для сравнительно больших проектов, которые требуют специфики: например, если надо сделать локализацию приложения, то можно действительно подключить разные ресурсы с разными строками.
У меня же есть мелкий микроконтроллер и прошивка. ОСи нет. Ресурсов нет. Функций чтения из файлов нет. Нет даже файловой системы :)
Я не знаю способа, как заставить AVR/gcc прочитать чего-нибудь из бинаря.
Ну это не значит что его нет, лишь то что ты плохо знаешь gcc. Речь не о загрузке файлов в рантайме, а о статической влинковке данных.
Ну это не значит что его нет, лишь то что ты плохо знаешь gcc.Да, это так. Послушаю твои варианты.
Речь не о загрузке файлов в рантайме, а о статической влинковке данных.Вообще-то ты процитировал меня. И я точно знаю, что я хотел сказать про рантайм :)
Короче, нету в avr+gcc функций вида LoadLibrary/fopen/etc. Ну, то есть, можно написать свой вариант, который будет делать любую фантазию, а-ля «файловая система поверх флеша AVR-ки», но «из коробки» ничего такого нет.
Короче, нету в avr+gcc функций вида LoadLibrary/fopen/etc.avr-gcc — это компилятор, причём тут функции ОС? Зачем разводить огороды с файловыми системами если нужно всего лишь обратиться к блоку данных во флеше? Проще всего сунуть его линковщику в виде объектного файла и спокойно потом обращаться по символам. Скорее всего есть и другие способы, но уже придётся ковырять мейкфайл и лд-скрипт, чего лучше избегать дабы не потонуть во всём этом линупсовом болоте.
причём тут функции ОС?Притом, что обычно функции перекодирования строк находятся в ОС. А доступ к ОС осуществляется через API, который доступен из компилятора. Но ОСи у нас нет. Приходится выкручиваться.
Проще всего...Да, наверное проще.
Но лично мне проще всего сунуть обычную человеко-читаемую строку в исходный код. И не прыгать с бубном вокруг линкера.
… дабы не потонуть во всём этом линупсовом болоте.Справедливости ради, gcc и вокруг — это и есть линуксовое болото, которое зачем-то притащили в винду.
define определяет макросы, include — вставляет файл.
Бинарный файл нельзя просто так скормить ни компилятору, ни линкеру. Прийдется его превратить в массив вида uint8_t array[]= {0x1, 0x2...'} какой-нибудь утилитой, а потом уже вставлять в код программы. Утилит есть масса готовых, да и самому такую сделать можно за пол-часа…
Бинарный файл нельзя просто так скормить ни компилятору, ни линкеру. Прийдется его превратить в массив вида uint8_t array[]= {0x1, 0x2...'} какой-нибудь утилитой, а потом уже вставлять в код программы. Утилит есть масса готовых, да и самому такую сделать можно за пол-часа…
- coredumped
- 26 апреля 2018, 12:08
- ↑
- ↓
Пардон, забыл совсем. На самом деле можно сделать объектный файл из бинарного с помощью
ld -r -b binary file.bin -o file.o, ну и потом уже собрать всё вместе. Обращаться нужно к с переменными _file_start _file_end и _file_size объявив их как extern. Всегда можно подсмотреть objdump-ом если забудете (objdump -t file.o).
Когда-то добавлял так блобы с fpga имиджами в бинарь микроконтроллера.
ld -r -b binary file.bin -o file.o, ну и потом уже собрать всё вместе. Обращаться нужно к с переменными _file_start _file_end и _file_size объявив их как extern. Всегда можно подсмотреть objdump-ом если забудете (objdump -t file.o).
Когда-то добавлял так блобы с fpga имиджами в бинарь микроконтроллера.
- coredumped
- 26 апреля 2018, 13:25
- ↑
- ↓
По теме. Конвертируйте строку в массив байтов
char s[]={0x10, 0x20, 0x00};
Для конвертирования можно написать небольшую программку, например на python3:text = 'наш текст'
ba = text.encode('cp1251') #или укажите другую кодировку
tout ='char s[] = {'
for b in ba:
tout += hex(b) + ','
tout += '0x00};'
print(tout)
- coredumped
- 26 апреля 2018, 18:58
- ↓
>> Но это вынуждает тащить ещё и питон.…
Напрягает, если к IDE приходится искать и приколхозивать сторонние подпрограммы…
Напрягает, если к IDE приходится искать и приколхозивать сторонние подпрограммы…
Ну если уж так хочется русских текстов… лучше, конечно, работать в *nix системе — там проблем нет никаких, а в винде — сплошные костыли.
- coredumped
- 30 апреля 2018, 17:19
- ↑
- ↓
Под винду нет нормальных компиляторв за вменяемые деньги, неприехавших из юникса. Или несколко тысяч $ плати, или gcc на костылях.
- coredumped
- 30 апреля 2018, 19:49
- ↑
- ↓
Под винду нет нормальных компиляторв за вменяемые деньги, неприехавших из юникса. Или несколко тысяч $ плати, или gcc на костылях.Насколько я понимаю, есть как минимум две бесплатные альтернативы: простейшие и бесплатные варианты Visual Studio и приползший с яблока clang.
Но это именно про winapi.
Если речь про AVR, то тут не очень понятно. gcc бесплатный, а про всё остальное я вообще не в курсе.
Я кросс-компиляторы имел ввиду. Для самой винды есть бесплатный vc toolkit.
- coredumped
- 01 мая 2018, 10:36
- ↑
- ↓
а в винде — сплошные костылиНичего не могу сказать про никсы, но вот в винде с кодировками всё хорошо. Начиная с w2k вкручена поддержка Unicode, причём прям в ядро. И все функции принимают широкие строки (есть парные функции, которые принимают ascii).
Другое дело, что поверх винды есть ещё и инструментарий, а-ля компиляторы. И там накладывается небольшой слой проблем вида «а как бы зашить строки в исходники». Есть на эту тему отличная статья.
Но на костыли это не очень похоже. И да, в контексте исходного поста — сборка под AVR в винде — это всё же кросс компиляция. Приходится приспосабливаться.
Комментарии (28)
RSS свернуть / развернуть