LINUX.ORG.RU

Вышел драйвер для GDI-принтеров Canon

 , , , ,


0

3

Первая работоспособная (хотя и не очень) версия открытого драйвера для принтеров Canon CAPT (LBP-****) вышла сегодня. В отличие от проприетарного драйвера, открытый является легковесным, не требует запуска демонов при загрузке системы и не саботирует работу принтеров других производителей.

При установке драйвера обратите внимание на выбор правильного устройства из списка (не usb://, а обязательно capt://) и на правильность файла *.ppd (в нем определены низкоуровневые параметры принтера, и с неправильным *.ppd принтер будет, скорее всего, печатать полосы).

Изменения:

  • полностью переписан код драйвера (с C на C++)
  • теперь драйвер работает через libusb и является бакэндом для CUPS
  • автоопределение принтеров
  • в основном устранены зависания принтера при сбоях печати

Недоработки:

  • не проверяется наличие бумаги!
  • при печати более чем одной страницы может печататься только первая
  • при печати очень сложных страниц иногда переполняется память принтера, «хвост» страницы обрезается
  • неправильные верхние и нижние поля

На сегодняшний день поддержан и проверен LBP-2900 и, вероятно, будет работать очень похожий на него LBP-3000. Другие модели не проверялись, так как их нет у разработчика.

ПРОЕКТУ ДЛЯ РАЗВИТИЯ ТРЕБУЮТСЯ РАЗРАБОТЧИКИ!

Требования: знание C++, наличие одного из CAPT-принтеров.

>>> Скачать



Проверено: anonymous_incognito ()
Последнее исправление: anonymous_incognito (всего исправлений: 2)

Уважаемый, идите в ReactOS код писать, хоть на плюсах хоть на ГЦЦ, у них есть где разгуляться и сообщество не быдловое как у линукса, пользы то реально больше будет.

anonymous
()
Ответ на: комментарий от HighwayStar

> хотя нет, не совсем, тестовая страница получается обрезана примерно на 5 мм с каждой стороны.

попробовал распечатать 2 страницы с текстом - распечаталось только половина первой, вторая вышла пустая

Какая модель принтера? Если не 2900, объявить как «частично работающую»?

Что касается полей, попробуй в ppd правильные числа подобрать. Хорошо бы измерить фактическую обрезку принтера хорошей линейкой (штангенциркулем? измерительным микроскопом?) и забить в ppd. Если есть возможность, хорошо бы для разных форматов бумаги.

Yampp
() автор топика
Ответ на: комментарий от Yampp

Какая модель принтера?

2900

обрезку попробую попозже измерить, те тестовые страницы как-то криво распечатались, в смысле похоже бумага лежала криво

HighwayStar ★★★★★
()
Ответ на: комментарий от Yampp

Когда с кодом работает несколько десятков человек, а код состоит из сотен тысяч строк, то НЕЛЬЗЯ требовать от каждого человека, чтобы он был телепатом и знал, что можно, а что нельзя делать с чужим кодом. За такими вещами ДОЛЖЕН следить компилятор.

Подождите. Человек, работающий с чужим кодом, должен знать, как с этим кодом работать, и никакой компилятор ему этого знания не заменит. Если человек вызывает memcpy() и не знает, что буфер-источник и буфер-назначение не должны перекрываться, то независимо от того, пишет он на С или С++, последствия для программы рано или позно будут плачевными.

А с какого гондураса сохраненная позиция может быть только одна? А если я десять позиций хочу сохранить?

Pos pos1 = in.save_pos(); in.read(x); Pos pos2 = in.save_pos(); in.read(y); if (! y) in.restore_pos(pos2); else if (x != y) in.restore_pos(pos1);

Я не могу понять, почему вы упорно не хотите решит эту задачу естественным путем и норовите запихнуть всё в какие-нибудь классы?

size_t pos1 = pos; read(&x); size_t pos2 = pos; read(&y); if (! y) pos = pos2; else if (x != y) pos = pos1;
Не? Вы написали то же самое, с той разницей, что 1) мифическая обезьяна не сможет вставить посреди этого кода что-нибудь типа pos = 123; 2) он несколько менее читабельный, чем мой; 3) требует написания отдельного дополнительного класса и 4) необходимо не забыть сделать методы inline и нужен достаточно современный компилятор, чтобы он произвел такой же эффективный код, как мой. И ради чего? Чтобы решить тривиальную задачу временного сохранения указателя!

anonymous
()
Ответ на: комментарий от Yampp

А в C++ инлайн может ходить в поля, недоступные другими средствами.

Преимущества от этого не стоят соответствующих затрат. Мы можем получить некоторую защиту от дурака но для этого нам нужно 1) написать целый отдельный класс (что, как мы видели, приведет к неизбежному раздуванию кода) и 2) любое изменение этого класса ведет к необходимости полной перекомпиляции всего кода, использующего этот класс!

anonymous
()
Ответ на: комментарий от Yampp

> Вот про это я каждый раз и говорю как про падение эффективности кода

У тебя кучи функционала ещё нет или работает через одно место — как ты сам написал в новости. Зато код супермегаэффективный... Трата времени на это вообще оправдана? Уж и не знаю, как нужно постараться, чтобы без этого задрачивания не обеспечить пропукную способность, необходимую для достижения максимальной скорости печати — даже если по уши malloc'ами обложиться.

fang
()
Ответ на: комментарий от anonymous

> Подождите. Человек, работающий с чужим кодом, должен знать, как с этим кодом работать, и никакой компилятор ему этого знания не заменит.

В реальной жизни очень часто человек видит чужой код впервые, а использовать его надо. Поэтому у такого кода должен быть четко отделен публичный интерфейс от внутреннего. В большинстве случаев это делается обычным делением на *.h/*.c и возможно как на Си, так и на C++. Исключение - жесткие ситуации, когда необходим inline; для этого случая в Си хорошего решения нет, в C++ есть private;

1) мифическая обезьяна не сможет вставить посреди этого кода что-нибудь типа pos = 123;

Это обычно не мифическая обезьяна, а программист, сонный после двух совещаний подряд, пишет pos = 123; вместо idx = 123;. В вышеприведенном примере кода эта ситуация рискует не пойматься на тестах, поскольку ситуация if (! y) скорее всего очень редкая и может не встретиться даже в синтетических тестах. Или, что еще хуже, программа просто выдаст неверный результат без каких-либо признаков ошибки, а на тестах это не поймать, потому что правильный ответ неизвестен. Отсюда берется желание возложить КАЖДУЮ мелочь на компилятор.

Если бы в Си typedef объявлял бы действительно новый тип, не преобразующийся никуда, то задачка решалась бы элементарно: typedef size_t pos_t. Но в Си такого нет. В C++ тоже нет, поэтому приходится использовать ближайший суррогат - класс.

2) он несколько менее читабельный, чем мой;

В больших zero-copy-программах, в которых несколько слоев абстракции работают с одним и тем же блоком памяти, ситуация меняется на прямо противоположную.

3) требует написания отдельного дополнительного класса

С тем же успехом можно жаловаться на использование лишнего оператора &. Класс сам по себе - бесплатная вещь. Это НЕ структура в Си. Просто на C++ нет смысла писать в обычном императивно-структурном стиле, для этого есть Си. C++ позволяет писать на выбор либо объектно-ориентированно, либо (как я чаще пишу) в почти функциональном стиле, со значительными элементами декларативного. Вплоть до того, что существенная часть логики программы пишется с помощью typedef, а функция main() состоит из одной строчки - конструирования получившегося класса. Здесь C++ конкурирует уже не с Си, а скорее с Haskell.

4) необходимо не забыть сделать методы inline и нужен достаточно современный компилятор

Фигня, последние 10 лет все компиляторы это делают даже без слова inline.

И ради чего? Чтобы решить тривиальную задачу временного сохранения указателя!

Ну давайте на ассемблере писать. Там еще проще. Только вот не надо забывать, что современные компиляторы оптимизируют код значительно лучше человека. И тут ровно та же самая ситуация.

Вот реальная задачка: на вход из сетевой качалки идет файл сложного формата (для определенности - XML), поступает из recv(), возможно, по байтику за раз. Входной поток надо парсить и много раз преобразовывать разными обработчиками, количество которых в будущем может меняться, выходные данные выдавать в виде блоков фиксированной длины. Требуемая скорость работы: реальное время, входной поток ограничен лишь скоростью гигабитной сети. Как сделать обработку без накопления данных в промежуточных буферах, истинно zero-copy? Даже использование простого sscanf недопустимо медленно.

Справитесь - присылайте резюме, нам такие нужны ;)

Yampp
() автор топика
Ответ на: комментарий от fang

> У тебя кучи функционала ещё нет или работает через одно место — как ты сам написал в новости. Зато код супермегаэффективный... Трата времени на это вообще оправдана?

Да, оправдана. НЕ из-за эффективности. Из-за гибкости. Функционал не работает потому, что о принтере известно ОЧЕНЬ мало. Хорошо, если 10% протокола расшифровано. То есть, НЕВОЗМОЖНО спроектировать драйвер «сразу», он гарантированно будет еще много раз переписываться и перекомпоновываться. Разумеется, я его оптимизировал ПО ЛЕГКОСТИ ИЗМЕНЕНИЙ такого рода. Просто я к счастью умею оптимизировать ОДНОВРЕМЕННО по легкости изменений и по скорости работы, и оптимальность скорости получил как бесплатное дополнение.

Что касается быстродействия, то лажануть на этом вполне можно. В виде битмэпки с разрешением 600 dpi типичная цветная страница весит около 40 мегабайт. Если тут не экономить, можно легко на полгига оперативной памяти развалиться. Что в общем-то и делает фирменный драйвер.

Между прочим, все, что не работает, вообще от кода не зависит. Зависит от другого.

1) Я НЕ ЗНАЮ, как принтер сигнализирует наличие бумаги. Поэтому в коде, проверяющем бумагу, написано вместо if (есть бумага) просто - if (true). Стандартный способ проверки бумаги через состояние порта, похоже, не подходит для Canon.

2) Я НЕ ЗНАЮ, как принтер определяет, сколько страниц печатать. Драйвер посылает в него страницу за страницей, но принтер почему-то печатает только первую, вторую выдает белой и намертво ставит статус «занят». Что ему не нравится, я не понимаю.

3) Я НЕ ЗНАЮ, как посылать в принтер страницы объемом больше мегабайта в сжатом виде. Их посылка отличается от посылки файлов меньшего размера. Принтер печатает только первый мегабайт от страницы, потом зависает. Ни в одном из сделанных мною и помощниками сниффов виндового драйвера такие страницы не встречались. Возможно, принтер вообще не умеет такое печатать, а виндовый драйвер решает проблему за счет тупого понижения разрешения на таких страницах до 300 dpi.

4) Я НЕ ЗНАЮ точного разрешения принтера (цифра 600 dpi - приблизительная), поэтому я не знаю точных (до 0.1 мм) размеров печатаемой области. Отсюда проблема неверных полей.

Я И НЕ УЗНАЮ всего этого, если господа анонимусы не возьмутся за снифферы USB и не начнут поставлять мне необходимые для реверс-инжениринга данные.

Yampp
() автор топика
Ответ на: комментарий от anonymous

1) написать целый отдельный класс (что, как мы видели, приведет к неизбежному раздуванию кода)

Бред сивой кобылы.

#include <cstdio>

class Foo
{
public:
    void operator() () { printf("Foo\n"); }
};

class Bar
{
public:
    void pr() { foo(); }
private:
    Foo foo;
};

int main()
{
    Bar x;
    x.pr();
    return 0;
}

gcc -S -O2 cpp.cpp

        .file   "cpp.cpp"
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "Foo\n"
        .text
        .p2align 4,,15
.globl main
        .type   main, @function
main:
.LFB33:
        .cfi_startproc
        .cfi_personality 0x0,__gxx_personality_v0
        pushl   %ebp
        .cfi_def_cfa_offset 8
        movl    %esp, %ebp
        .cfi_offset 5, -8
        .cfi_def_cfa_register 5
        andl    $-16, %esp
        subl    $16, %esp
        movl    $.LC0, 4(%esp)
        movl    $1, (%esp)
        call    __printf_chk
        xorl    %eax, %eax
        leave
        ret
        .cfi_endproc
.LFE33:
        .size   main, .-main
        .ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
        .section        .note.GNU-stack,"",@progbits

Легко видеть, что в ассемблере нет ни единого следа классов. Несмотря на то, что слова inline не было.

2) любое изменение этого класса ведет к необходимости полной перекомпиляции всего кода, использующего этот класс!

30 секунд жалко?

Yampp
() автор топика
Ответ на: комментарий от Yampp

В реальной жизни очень часто человек видит чужой код впервые, а использовать его надо.

Любой нормальный человек перед использованием кода хотя бы полюбопытствует, что этот код делает. У любого кода могут быть ограничения и С++ здесь не исключение. Довести эти ограничения до сведения программиста - не задача компилятора, я считаю.

Это обычно не мифическая обезьяна, а программист, сонный после двух совещаний подряд, пишет pos = 123; вместо idx = 123;.

Ну, сонный программист может и вообще все файлы удалить. Может быть компилятор и за этой мелочью должен следить?

С тем же успехом можно жаловаться на использование лишнего оператора &. Класс сам по себе - бесплатная вещь.

Класс - бесплатная вещь, но вот время написания даже минимального класса несопоставимо с временем написания оператора &. И писать новый класс каждый раз для того, чтобы скопировать одну переменную в другую, по-моему, непозволительная трата времени.

Фигня, последние 10 лет все компиляторы это делают даже без слова inline.

Если всё, что делает класс - это копирование одной переменной в другую, то да. А если что-то посложнее и какие-то функции вынесены в отдельный модуль, то всё может быть не так однозначно.

Ну давайте на ассемблере писать. Там еще проще. Только вот не надо забывать, что современные компиляторы оптимизируют код значительно лучше человека. И тут ровно та же самая ситуация.

Если бы современные компиляторы оптимизировали код значительно лучше человека, в ядрах современных ОС не было бы столько кода на ассемблере. Дело в том, что компилятор создает приемлемо-оптимальный код несоизмеримо быстрее, чем человек создаст идеально-оптимальный код. Плюс несоизмеримы затраты на поддержку этого кода. Поэтому использование компилятора гораздо выгоднее. Но когда нужна производительность в узких местах, пользуются опять ассемблером.

Даже использование простого sscanf недопустимо медленно.

Вы так пишете, как будто sscanf - эталон быстродействия :)

Справитесь - присылайте резюме, нам такие нужны ;)

Спасибо, конечно, но нас пока и здесь неплохо кормят ;)

anonymous
()

Вышел багфикс-релиз 0.1.1

ChangeLog:

Автоопределение путей инсталляции CUPS (решает проблему «не найден cupscat» при установке через make install без PREFIX= на некоторых дистрибутивах)

Жесткое указание числа пикселей в строке изображения (решает проблему «печатаются полосы» на некоторых версиях CUPS)

Экспериментальная поддержка LBP-810 (не тестировалась, у меня нет такого принтера)

Поддержка принтеров:

По-прежнему проверен только LBP-2900.

Если у вас черно-белый 600 dpi принтер LPB-2xxx, 3xxx и старше, попробуйте его с PPD от LBP-2900 и сообщите, заработал или нет.

Если у вас цветной принтер или принтер более чем на 600 dpi, все равно попробуйте его с PPD от LBP-2900 - должно напечататься испорченное изображение. Если напечатается, напишите мне в почту, и мы вместе сделаем правильный PPD для вашей модели.

Если у вас LBP-810 или LBP-1120, попробуйте его с PPD от LBP-810 и сообщите, если заработает. (Если не заработает, сообщать не надо, это не сюрприз; тем не менее, отпишитесь в почту, если вы готовы помогать в разработке).

Если у вас МФУ с маркировкой, начинающейся на MF-, то это не CAPT-принтер, вам этот драйвер не поможет.

Поддержка фич:

Гарантируется печать только одной страницы, наличие бумаги не проверяется. Если хотите помочь в реверс-инжениринге для поддержки этих фич, пишите в почту. Адрес - в исходниках.

Yampp
() автор топика
Ответ на: комментарий от Yampp

Бред сивой кобылы.

Пардон, наврал. С++ раздувает код даже без использования классов.

30 секунд жалко?

Мне - нет. А вот насчет тех, кто купили мою библиотеку, написали на ней свой продукт и распространили его еще на 100500 клиентов, не уверен.

anonymous
()
Ответ на: комментарий от anonymous

> Довести эти ограничения до сведения программиста - не задача компилятора, я считаю.

Компилятор поддерживает возможность хватания за руку программиста, пишущего бред. Определенные приемы написания программы позволяют эту возможность эффективно задействовать. В качестве альтернативы можно пользоваться разного рода lint-утилитами для проверки кода, и в общем-то это неплохо было бы, если бы люди не ленились этим пользоваться. Компилятор по крайней мере НЕ ЗАБУДЕШЬ запустить.

Ну, сонный программист может и вообще все файлы удалить. Может быть компилятор и за этой мелочью должен следить?

За этим следит система контроля версий (SVN, GIT и т.п.), которая позволяет легко отменить такое действие.

А если что-то посложнее и какие-то функции вынесены в отдельный модуль, то всё может быть не так однозначно.

Из опыта работы: все равно нормально оптимизирует. Вернее, есть некоторые вполне конкретные синтаксические конструкции, способные оптимизацию убить, тот же new в ряде случаев, но они в коде достаточно заметны. Единственное, что я очень рад был бы запретить - это cast в стиле Си (через скобки), поскольку он совершенно в коде глаз не режет, а поведение у него довольно-таки непредсказуемое.

Если бы современные компиляторы оптимизировали код значительно лучше человека, в ядрах современных ОС не было бы столько кода на ассемблере. Дело в том, что компилятор создает приемлемо-оптимальный код несоизмеримо быстрее, чем человек создаст идеально-оптимальный код. Плюс несоизмеримы затраты на поддержку этого кода. Поэтому использование компилятора гораздо выгоднее. Но когда нужна производительность в узких местах, пользуются опять ассемблером.

На самом деле, пишут на ассемблере давно уже не ради оптимальности. Дело в другом. Некоторые вещи, например атомарные обращения к переменным (вссемблерные lock; cmpxchg и т.п.), работа с MMU и подобные штуки требуют контроля над такими вещами, как конкретные инструкции и конкретный порядок инструкций, определенные имена регистров и т.п. Такие вещи в принципе нельзя написать на ЯВУ, потому что их просто нет в синтаксисе ЯВУ. В ядре системы таких вещей очень много.

Вообще, еще раз повторюсь: Си и C++ - просто разные языки. На Си очень неудобно писать в функциональном стиле, а на Haskell не попишешь в императивном. Для написания данной конкретной программы я выбрал парадигму и соответствующий стиль, в котором на Си писать неудобно, а на C++ легко. Поэтому выбором языка стал C++. Есть обратные ситуации, когда на Си писать легко, а на C++ неудобно, если только не вырубить в опциях компиляции всю C++-ность. Как я уже говорил, утилиты для реверсинга были именно такими, ну и в принципе я несколько сотен таких вещей написал как минимум.

То, что для драйвера выбран C++, а не Си - это во многом «заслуга» libusb с ее работой с устройствами. Она очень просит ООП, а ООП на Си делать неудобно.

Yampp
() автор топика
Ответ на: комментарий от Yampp

Легко видеть, что в ассемблере нет ни единого следа классов. Несмотря на то, что слова inline не было.

Замените printf на родной сиплюсплюсный cout и посмотрите что будет в листинге.

anonymous
()
Ответ на: комментарий от anonymous

> Мне - нет. А вот насчет тех, кто купили мою библиотеку, написали на ней свой продукт и распространили его еще на 100500 клиентов, не уверен.

Не надо смешивать библиотечные классы для внутреннего пользования и публичный интерфейс динамической библиотеки, конечного продукта для распространения. Динамическая библиотека инлайновой по определению быть не может, а значит, нет никакого резона делать private в хедерах.

Интерфейс динамической библиотеки НИКОГДА не должен использовать классы, даже если библиотека написана на C++. Внешний интерфейс должен быть стабильным и extern «C». Это единственный истинно независимый от языка и компилятора интерфейс. Во всех остальных случаях будет хотя бы от версии компилятора зависимость, даже если код библиотеки не менять.

Yampp
() автор топика
Ответ на: комментарий от anonymous

> Замените printf на родной сиплюсплюсный cout и посмотрите что будет в листинге.

Может быть, еще на вывод окна в GUI заменить посоветуете?

Добавится (тяжелая) поддержка правильной буферизации вывода в случае многопоточного приложения и линковка с pthread, разумеется. Не надо запорожец с камазом сравнивать - cout НЕ является заменой для printf, у него совершенно ДРУГИЕ возможности, он, в отличие от printf, буферизует правильно в сложных случаях. Замена printf на cout не более равноценна, чем замена printf на виндовый CreateDialogEx!

Yampp
() автор топика
Ответ на: комментарий от Yampp

> Для корректной работы обработки ошибок нужны автоматические деструкторы. Иначе будете в каждой строчке if(error) free(memory) писать. И допишетесь до утечки памяти в лучшем случае.

Ну при использовании C++ нужна еще культура следования принципу RAII (у автора она есть).

А в современном C для обработки ошибок часто используется цепочка освобождалок ресурсов в конце каждой функции и конструкции вида if (error) goto в_середину_этой_цепочки; , что, конечно, создает риск забыть ее обновить при внесении изменений в функцию.

AEP ★★★★★
()
Ответ на: комментарий от Yampp

Не надо смешивать библиотечные классы для внутреннего пользования и публичный интерфейс динамической библиотеки, конечного продукта для распространения. Динамическая библиотека инлайновой по определению быть не может, а значит, нет никакого резона делать private в хедерах.

А почему вы решили, что я имею ввиду именно динамическую библиотеку? Библиотеки бывают и статическими.

Может быть, еще на вывод окна в GUI заменить посоветуете?

Я посоветую использование родного для этого языка оператора стандартного вывода.

Добавится (тяжелая) поддержка правильной буферизации вывода в случае многопоточного приложения и линковка с pthread, разумеется. Не надо запорожец с камазом сравнивать - cout НЕ является заменой для printf, у него совершенно ДРУГИЕ возможности, он, в отличие от printf, буферизует правильно в сложных случаях.

А я и не сравнивал printf и cout, если вы заметили. Я лишь подтвердил своё высказывание о том, что С++ генерит лишний код даже без создания классов :)

Замена printf на cout не более равноценна, чем замена printf на виндовый CreateDialogEx!

Но, тем не менее, во всей литературе по С++ программы «Hello world» почему-то используют именно cout, а не printf.

anonymous
()
Ответ на: комментарий от anonymous

> Библиотеки бывают и статическими.

Замена статической библиотеки - все равно перекомпиляция, так или иначе; если она чужая, то глупо рисковать оставлять старый *.h, а замена *.h на новую версию вызовет все равно перекомпиляцию всего мира. Следовательно, вышесказанное для статических библиотек бессмысленно все равно. Следовательно, проблема относится только к динамическим библиотекам.

Я лишь подтвердил своё высказывание о том, что С++ генерит лишний код даже без создания классов :)

Вы ничего не подтвердили кроме того, что библиотека, содержащая cout, тяжелее, чем библиотека, содержащая printf. Это и так всем известно.

Но, тем не менее, во всей литературе по С++ программы «Hello world» почему-то используют именно cout, а не printf.

Также в литературе советуют все деструкторы всегда делать виртуальными, не перегружать невиртуальные методы, всегда делать интерфейс отдельным классом и обращаться к имплементации через указатель и т.п. Это связано с необходимостью начального обучения: написание на C++ с использованием невиртуальной перегрузки, шаблонного наследования и других подобных приемов требует хорошего знания языка как такового. Поэтому до полного знакомства со всеми тонкостями самого языка эти приемы не показывают, а для «негрокодеров» в энтерпрайзе они вообще административно запрещаются. Пилотов обычно тоже сначала на кукурузнике учат, и только потом на МиГ пересаживают.

Скажем, вы можете навскидку сказать, как происходит преобразование типов переменных при передаче их функции printf и какие вызовутся перегруженные операторы кастов, если таковые имеются? Вы считаете, что это нужно объяснять сразу после показа кода Hello World, заодно с объяснением, почему printf не печатает std::string? Разумеется, авторы учебников не забивают новичкам голову такими тонкостями и просто показывают cout.

Yampp
() автор топика
Ответ на: комментарий от Yampp

Вы ничего не подтвердили кроме того, что библиотека, содержащая cout, тяжелее, чем библиотека, содержащая printf. Это и так всем известно.

Так код генерится компилятором! А «тяжесть» библиотеки, содержащей cout, тут ни при чем, я ее к тому листингу не прилинковываю.

Скажем, вы можете навскидку сказать, как происходит преобразование типов переменных при передаче их функции printf и какие вызовутся перегруженные операторы кастов, если таковые имеются? Вы считаете, что это нужно объяснять сразу после показа кода Hello World, заодно с объяснением, почему printf не печатает std::string? Разумеется, авторы учебников не забивают новичкам голову такими тонкостями и просто показывают cout.

Подозреваю, что они и сами этого доподлинно не знают :) И не должны этого знать нормальные люди, особенно если они стараются возложить каждую мелочь на компилятор :)

anonymous
()
Ответ на: комментарий от Yampp

Писать на плюсах без использования ООП некошерно. А new в коде быть не должно, это да. Выделение памяти лучше инкапсулировать в классы и шаблоны.

А вообще, C++ — быдлоязык. Мало того, что стандарт ужасен, так его еще и ни один компилятор не поддерживает.

anonymous
()
Ответ на: комментарий от Yampp

> Ну давайте на ассемблере писать. Там еще проще. Только вот не надо забывать, что современные компиляторы оптимизируют код значительно лучше человека. И тут ровно та же самая ситуация.

Кстати, неплохая идея. А еще можно вообще ничего не писать, а решать все аппаратно. Правда, там дебаг не очень удобный.

anonymous
()
Ответ на: комментарий от anonymous

> Так код генерится компилятором! А «тяжесть» библиотеки, содержащей cout, тут ни при чем, я ее к тому листингу не прилинковываю.

Код статической инициализации не компилятор придумал, он НАПИСАН в файле iostream (точнее, в файлах, которые этот iostream подключает), и компилятор всего лишь ВСТАВЛЯЕТ этот код в программу по первому требованию. «Первым требованием» является обращение к cout.

Подозреваю, что они и сами этого доподлинно не знают :)

Это вполне четко регламентировано в стандарте и разобрано в учебниках advanced level.

И не должны этого знать нормальные люди, особенно если они стараются возложить каждую мелочь на компилятор :)

Если говорить точнее, то нормальные люди могут таких вещей не помнить, но знать об их СУЩЕСТВОВАНИИ обязаны. Достаточно на самом деле лишь помнить, какому типу данных какая маска в printf соответствует, и во всех случаях несоответствия ставить static_cast. Здесь проблема скорее в том, как объяснить это новичкам, которые только начали изучать язык и еще не знают, что такое static_cast.

Выделение памяти лучше инкапсулировать в классы и шаблоны.

Еще лучше его избегать вовсе: как правило, память на куче выделяют не потому, что она нужна именно на куче, а потому, что так писать удобнее.

А вообще, C++ — быдлоязык. Мало того, что стандарт ужасен, так его еще и ни один компилятор не поддерживает.

Согласен, как ни странно это звучит. C++ - очень плохой язык. Просто все остальные мультипарадигменные языки (C#, Java, D и т.д.) еще хуже. (Насчет D можно поспорить, но пока у него в стандартной библиотеке такой бардак и компиляторы такие слабые, пользоваться им в реальных проектах затруднительно.) Вот и получается, что если я не хочу писать в простом императивном стиле, я вынужден использовать C++.

Yampp
() автор топика
Ответ на: комментарий от Yampp

> Вообще было бы очень интересно посмотреть на не-USB-принтеры. Их поддержка планируется, если, конечно, она вообще хоть кому-нибудь еще нужна.

Да нужна. При сколь нибуть серьезных требованиях к доступности печати USB во внимание не берется изза ошибок дизайна собственно USB. Остается или COM или Ethernet. COM обычно дешевле.

cvv ★★★★★
()
Ответ на: комментарий от Yampp

>Вот реальная задачка

мне было бы интересно с этим повоевать но жалко что совсем плохо со свободным временем.

cvv ★★★★★
()
Ответ на: комментарий от cvv

> Остается или COM или Ethernet. COM обычно дешевле.
Эмм.... а где сейчас взять принтер на COM? Вроде только LPT есть ещё, если не вымерли.

Magister2k7
()
Ответ на: комментарий от cvv

Вы COM и LPT не путаете? Стандартным legacy-интерфейсом для принтеров является LPT. COM-принтеры - большая редкость, хотя и существуют. За исключением принтеров для термобумаги (чеков), они как правило COM.

Yampp
() автор топика
Ответ на: комментарий от cvv

> мне было бы интересно с этим повоевать но жалко что совсем плохо со свободным временем.

Для начала попробуйте отослать в принтер вот такую последовательность байтов (просто в /dev/чегототам сделать write()):

0xA1 0xA1 0x04 0x00 (это команда «запрос возможностей принтера»)

и прочитать ответ (просто read() на достаточно большой буфер). CAPT-принтер Canon должен на это ответить последовательностью байтов, начинающейся с A1 A1, затем два байта - длина (LSB first), потом хвост данных неизвестного назначения. Если это так, то поддержать принтер ничего не стоит - достаточно в драйвер дописать всего лишь код с read/write для файлов в /dev.

Yampp
() автор топика
Ответ на: комментарий от Yampp

боже, откуда столько пафоса у человека, парсящего какой-то xml, т.е. по сути, паразита, занимающегося ненужнам обществу трудом?

anonymous
()
Ответ на: комментарий от anonymous

Хех... :) Анонимус не представляет, ГДЕ этот парсер работает, ЧТО он парсит и СКОЛЬКО раз сам же этот анонимус результатами парсинга воспользовался :) Лол, в общем. Маленькая подсказка: несколько миллионов посетителей на сайте в день, общий объем прошедшей через парсеры информации приближается к петабайту.

Yampp
() автор топика

Требуется помощь в реверс-инжениринге многостраничной печати

Установлено, что за количество успешно печатаемых страниц скорее всего отвечает пакет, посылаемый в команде A1 E1 (единственное полностью загадочное место, если не считать A1-A1-ответа). Возможно, влияет также порядок команд отдачи данных на печать - загрузить-печатать-загрузить-печатать-..., или загрузить-загрузить-печатать-печатать-загрузить-печатать-.... По имеющимся у меня сниффам определить это невозможно.

Сниффы присылать мне НЕ НАДО, я физически не могу принять и проанализировать все, что мне присылают. Нужны результаты анализа. Пробуйте изменять пакет A1 E1 (он лежит в captmagic.cpp под названием magicbuf_1):

/* A1 E1 */
static const uint8_t magicbuf_1[] = {
    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x0C, 0x00, 0x0C, 0x00, 0x16, 0x00, 0x00, 0x00,
    0x01, 0x01, 0x01, 0x00, 0xD4, 0xFE, 0x98, 0xFE,
    и т.д.
модифицировать логику цикла в printfsm.cpp - вот это место:

        wait_ready();

        if (! prepare_page())
        {
            fprintf(stderr, "DEBUG: Job done\n");
            m_io.sendrecv(CAPT_JOB_END, ipage);
            break;
        }
        ++ipage;

        m_io.send(CAPT_SET_PARMS, captmagic_parms, captmagic_parms_size);
        upload_page();
        wait_paper();
        fprintf(stderr, "DEBUG: Printing page\n");
        m_io.sendrecv(CAPT_FIRE, ipage);
        wait_page(ipage);

и смотрите, что получится. За универсальностью, правильностью и т.д. следить не надо - как угодно подхакайте код, лишь бы напечаталось 2-3-4-5 страниц. И скажите мне, при каких условиях они печатаются, а при каких нет. Если удастся поймать эти условия, я сразу смогу сделать нормальную печать произвольного числа страниц.

Менять помеченные комментарием байтики в магической последовательности уже пробовал, не меняется ничего. Видимо, еще какую-то мелочь проглядел.

Yampp
() автор топика
Ответ на: комментарий от Magister2k7

под заказ у поставщиков встраиваемого оборудования. ну чтото типа «Индустриального компьютера» в украине. LPT это немного другая ниша, тоесть ширпотреб, и поэтому практически вытеснены USB.

cvv ★★★★★
()
Ответ на: комментарий от Yampp

Нет. COM это не legacy. это специфическая ниша встраиваемой техники где требуется высокая доступность. принтеры для чеков именно из этой оперы. не так давно приходилось к одному компу подключать 6 термопринтеров через один USB. За одно выяснил что сделал большую глупость:(

cvv ★★★★★
()
Ответ на: комментарий от cvv

С индустриальным и встраиваемым оборудованием все понятно, там действительно COM - это стандарт. Но речь шла о вполне конкретной модели - LBP-810 на COM-порте. Насколько мне известно, ни один из работающих по протоколу CAPT принтеров Canon LBP-*** не выпускался под COM (и смысла в этом никакого я лично не вижу, потому что эти принтеры - типичный ширпотребный low-end подешевле, и чем «проще» для юзера разъем, тем лучше).

Интересно, что именно не так было с USB. Сам по себе USB - достаточно хороший, хотя и сложный, протокол, он имеет лишь два ограничения (я бы не стал их недостатками называть): а) у него по умолчанию большая латентность передачи данных (существует режим реального времени низкой латентности, но он не поддерживается массовыми недорогими USB-железками и имеет много других ограничений и, насколько мне известно, поддержан только в unix-подобных системах, в линукс - только при установке RTAI), и б) степень защиты и помехоустойчивости кабелей офисная, а не индустриальная, и «индустриально-усиленного» стандарта не существует.

Если вас не затруднит, расскажите, что именно плохо работало с USB? Казалось бы, проброска обычного последовательного канала RS232 через USB - очень простая вещь. Или настолько не повезло с чипами конвертеров, глючные оказались?

А истинное zero-copy - да, интересная вещь :) Она решается в терминах функционального программирования, можно на функциональном языке, но к счастью и C++ эту парадигму предусматривает в достаточной степени через классы-функторы и шаблоны. Местами приходится использовать генерированный код - там, где идут таблицы парсинга.

Yampp
() автор топика
Ответ на: комментарий от cvv

Хм... интересно. Хоть мне пока что практически нигде не нужно было, но для общего развития - можете дать пару ссылочек по теме?

Magister2k7
()
Ответ на: комментарий от Magister2k7

> Хоть мне пока что практически нигде не нужно было, но для общего развития - можете дать пару ссылочек по теме?

По какой именно? Попробую подобрать (с ссылками туго, информация такого рода собирается по крупицам отовсюду, никто ее не удосужился собрать в одном месте).

Yampp
() автор топика
Ответ на: комментарий от Magister2k7

> По теме принтеров с COM-интерфейсом. Где взять, в чем преимущества, где их лучше использовать и почему.

Особой литературы нету.

COM-интерфейс отличается исключительной электрической прочностью и помехоустойчивостью. Он 12-вольтовый, может работать на длинных проводах и в условиях сильных помех. Аппаратная реализация протокола очень проста, RS232 (без 12-вольтового преобразователя уровней) есть даже на микроконтроллерах стоимостью 1 доллар, а практически во всех устройствах где-то внутри есть скрытый 3- или 5-вольтовый COM-порт. Все это делает COM идеальным кандидатом на низкоскоростной интерфейс для индустриальных применений и встраиваемых систем.

RS232, наряду с (Industrial) Ethernet и RS485, является «кондовым» интерфейсом для надежной заводской техники. К тому же, он не менялся много лет. Поэтому, всегда, когда возможностей RS232 хватает, в подобной технике имеет смысл использовать именно его.

А сколько денег платят тем, кто осилил zero-copy?

Коммерческая тайна. Зарплаты высокие. Вообще zero-copy здесь - скорее иллюстрация к проблеме обработки огромных объемов информации, зачастую в неоптимальном формате, приходящих извне. При кластере из нескольких сотен машин по нескольку тысяч долларов каждая всего лишь 1% ресурсов в денежном выражении - десятки килобаксов. А нагрузки такие, что даже для самых современных машин в больших количествах это предел возможностей. Поэтому такие вещи, как zero-copy - насущная необходимость, иначе просто работать не будет. Иногда считаешь каждый такт, каждый байт кеша процессора...

Yampp
() автор топика
Ответ на: комментарий от Yampp

> Особой литературы нету.

COM-интерфейс отличается исключительной электрической прочностью и помехоустойчивостью. Он 12-вольтовый, может работать на длинных проводах и в условиях сильных помех. Аппаратная реализация протокола очень проста, RS232 (без 12-вольтового преобразователя уровней) есть даже на микроконтроллерах стоимостью 1 доллар, а практически во всех устройствах где-то внутри есть скрытый 3- или 5-вольтовый COM-порт. Все это делает COM идеальным кандидатом на низкоскоростной интерфейс для индустриальных применений и встраиваемых систем.


Спасибо за подробное объяснение. Понял, что пока что мне это ни к чему, но информация лишней не бывает.
В нужный момент обязательно вспомню :)

Magister2k7
()
Ответ на: комментарий от Vudod

Разрабы, наверное, молодцы, но зачем они это делают, не ясно, если есть нормально работающие коммерческие дрова.

Если бы... For example, на LBP 3010 с этими коммерческими дровами изображения печатаются с черепашьей скоростью. Что уж говорить о стабильности, когда бекэнд или демон падают ни с того ни с сего, либо жрут процессор на 100% (когда ничего не печатается).

tiandrey ★★★★★
()
Ответ на: комментарий от Yampp

да с 2900 хотя бы разобраться)) а потом и остальные можно будет допилить.. сейчас 2900 работает корректно в рамках заявленых багов. .

alex208210
()
Ответ на: комментарий от alex208210

Другие принтеры тоже важны именно для поддержки 2900. По различиям в поведении принтеров можно понять, что важно, а что нет в протоколе.

Сейчас первоочередная проблема - многостраничная печать. Ответственная за нее часть протокола неизвестна почти полностью. На втором месте - проверка наличия бумаги. Все остальное - минорные проблемы, легко решаемые при наличии свободных разработчиков и тестеров.

Yampp
() автор топика

> при печати более чем одной страницы может печататься только первая

Ничего себе «недоработка». Я бы это назвал epic fail.

при печати очень сложных страниц иногда переполняется память принтера, «хвост» страницы обрезается

неправильные верхние и нижние поля

Такие косяки и раньше были... увы. что улучшили то?

BattleCoder ★★★★★
()
Ответ на: комментарий от Yampp

> Интересно, что именно не так было с USB. Сам по себе USB - достаточно хороший, хотя и сложный, протокол.

этот протокол недоконца продуман. Со слов разработчиков дров FTDI в протоколе возможны дедлоки обмена которые можно разрешить только передергиванием разьема или обестачиванием одного из устройств. некоторые назвают USB «поделкой индусских студентов».

Analog Devices имеет аппаратно-програмные наработки по «индустриальному усилению» USB. Эмбедеры в основной своей массе скептически воспринимают эти наработки.

Если вас не затруднит, расскажите, что именно плохо работало с USB? Казалось бы, проброска обычного последовательного канала RS232 через USB - очень простая вещь. Или настолько не повезло с чипами конвертеров, глючные оказались?

были проблемы со стабильностью обмена по USB. Корнем проблемы оказалось то что девайс имел собственное питание. В этой ситации сносную работу можно получить только гальванически отвязав USB от девайса. Это недоработка хардварной части стандарта USB. Мы использовали комбинацию FTDI232 + микроконтроллер + пара счетверенных уартов.

А истинное zero-copy - да, интересная вещь :)

Я кстати эту задачу пока решаю удалением избыточных сисколов и прореживанием существующих. поэтому мне было бы интересно пощупать систему где этого недостаточно.

cvv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.