В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Простейшие вопросы в области инженерной разработки
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

Всем привет!
Возникла потребность использовать внешнюю DLL из приложения на LV.
Раньше я использовать ее в среде LV2010 для печати картинки на принтер. У меня есть готовая и хорошо работает.
Сейчас я апгрейдил приложение на LV до платформы x64 бит, и хотел бы пересобрать и эту DLL, чтобы не изобретать велосипед.
Но с тех пор у Винды поменялся интерфейс в DLL файлах, и я не знаю: в какой среде переписать эту коротенькую утилитку: толи в CPP то ли в C#(.NET).
Или воспроизвести это в среде LV?
Вся задача: однобитный битмап (файл .BMP) распечатать на принтере в точках принтера.

Я бы предпочел это сделать в самой LV. Но пока не знаю: использование NIReport представляется очень громоздким.
И как в нем добиться, чтобы растровая картинка печаталась в точках принтера?
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3939
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 12 раз
Поблагодарили: 133 раза
Контактная информация:

Re: В какой средк (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение dadreamer »

Если в коде DLL в основном WinAPI вызывается, то будет не так сложно воспроизвести его на диаграмме с помощью вызовов CLFN. Однако, если там какие-то C- (и тем более C++) специфичные штуки заюзаны, то проще, наверное, перекомпилить под 64 бита. В общем, покажите код библиотеки, тогда можно будет сказать точнее.
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

Re: В какой средк (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

В этой старенькой DLL кода на две странички.
Прицепляю файлик на СРР.
Но проблема в том, что в этой старой редакции использовался класс CImage для чтения BMP_файла.
Теперь Windows его не поддерживает и надо искать альтернативу.
Я попытался сделать то же в LV2021 через NIReport.
Но он почему-то все время кидает на дефолтный принтер, что меня не устраивает. А когда я делаю принтер дефолтным, то виснет на отправке и все. Хотел макетик битмапа прицепить, но ругается на недопустимый файл.
Вложения
PrintBMP2.cpp
(12.08 КБ) 68 скачиваний
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3939
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 12 раз
Поблагодарили: 133 раза
Контактная информация:

Re: В какой средк (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение dadreamer »

В принципе, этот код несложно переписать на инструментах :labview: , займёт где-то пол-часа - час работы. Но я попробовал скомпилировать в MS Visual Studio 2015 и особых граблей не вылезло. 64-битная версия тоже компилируется. Не знаю, как будет работать, нужно проверять. Вероятно, также потребует установки Microsoft Visual C++ 2015 Redistributable.
Вложения
PrintBMP.rar
(12.11 КБ) 114 скачиваний
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

Спасибо! Я сделал то же самое в VS2020.
Код простой и компилится без затей. Проблема в том, что чтение битмапа производится классом CImage.
И чтение файла однобитного (ч/б) битмапа в новой платформе всегда приводит к ошибке в этой строке. :-(
Хотя файл читают все графические программы.
Когда я вызываю справку по CImage, там написано, что на платформе Windows этот класс не поддерживается.
Но опыт работы с графикой в CPP у меня уже старый, тоже последний раз пользовался в VS2015.
Новая Винда теперь вся на платформе .Net. Поэтому и вопрос задал о среде разработки DLL.
Видимо, система классов теперь иная. Последний раз приходилось писать DLL в VS2020 в C# для работы с устройством DIO.
Правда, на платформе х32.
Но с графикой давно не работал.
Попробовал смастерить эту процедуру средствами LV через NI Report.
Работать работает, но результата нет: не видит указываемого принтера и фигачит на дефолтный. А мне надо на предписанный.
Но даже делая принтер дефолтным, ничего на него не вылазит и процедура виснет.
Теперь до понедельника буду кумекать.
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3939
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 12 раз
Поблагодарили: 133 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение dadreamer »

PAG писал(а): 25 ноя 2023, 16:43Когда я вызываю справку по CImage, там написано, что на платформе Windows этот класс не поддерживается.
То, что на MSDN написано
This class and its members cannot be used in applications that execute in the Windows Runtime.
к обычным приложениям Windows не относится. Это касается только программ на архитектуре Windows Runtime (WinRT) (Metro-приложения):
StackOverflow - MSDN: "This class and its members cannot be used in applications that execute in the Windows Runtime"
Wikipedia - Windows Runtime
Проблема там в другом. Я ещё раз взглянул на код. Ещё в первый раз меня кое что смутило, но я подумал, что так и должно быть...
Вы объявляете эти две переменных:

Код: Выделить всё

char		 PrinterName[120];
char		 BMPFileName[120];
И далее используете:

Код: Выделить всё

if (!OpenPrinter(PrinterName, &hPrinterHandle, NULL))

Код: Выделить всё

FILE *BMPfile = fopen(BMPFileName, "r");

Код: Выделить всё

if (Image.Load(BMPFileName))
Но ни для PrinterName, ни для BMPFileName не установлено имя/путь. То есть, переменные объявили, а ничего им не присвоили. Как это вообще работало? :dntknw:

upd: ради интереса даже на XP проверил. В том виде, как есть, не работает. Если задать имя принтера и путь до bmp, то печатает. Правда почему-то делает выходную картинку аж 4672*6774 пикселя, видимо, надо покрутить какие-то параметры.
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

Имя принтера и имя файла - внешние. Передаются через аргументы вызова функции из приложения.
Приведенные код - тело функции печати.
Она вызывается из главной функции DLL (в этом фрагменте ее нет).

Мне было бы проще сделать DLL на C#: там всего три строчки написать.
Но я не уверен, что механизм работы с памятью в .Net будет адекватен при работе DLL в среде LV.
И я не получу "нежданчики" в процессе длительной работы приложения на LV (периодических вызовов функции печати).

И вообще: если создавать DLL для среды LV, то какой язык программирования использовать?
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

Решил задачу на низком уровне: написал три функции на С++ с использованием GDI и сделал DLL.
С C# рисковать не стал: слишком много версий .NET расплодилось.
Но с NI Report - отдельная проблема, блин.
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

Решил задачу на низком уровне: написал три функции на С++ с использованием WIN GDI и сделал DLL. Все поехало.
С C# рисковать не стал: слишком много версий .NET расплодилось.
Но с NI Report - отдельная проблема, блин.
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3939
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 12 раз
Поблагодарили: 133 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение dadreamer »

Некогда было этим заниматься, да и там, как оказалось, чуть больше времени потребовалось для переноса на БД. Кластеры, конечно, громоздкие, но с этим ничего не сделать. Можно оформить в SubVI, мне просто лень, два я сделал, на этом закончил.
printer test 3.vi
lv2019
(22.16 КБ) 87 скачиваний
Connect Printer 2.vi
lv2019
(30.32 КБ) 92 скачивания
Close Printer.vi
lv2019
(11.08 КБ) 29 скачиваний
Проверял как в 32-, так и в 64-битном :labview: , версии 2019, 2021 и 2023. Графика в *.bmp на форум не аттачится, картинки для проверки в MS Paint за пару секунд можно сделать. Пока успел проверить только на виртуальных принтерах: Adobe PDF, CutePDF Writer, doPDF 8 и Snagit 11/12. Любопытно, что у каждого принтера есть свои нюансы при печати, хотя по логике все должны отрабатывать задание одинаково. Например, CutePDF Writer не воспринимает пользовательские размеры листа, пока ему не задашь dmPaperSize = DMPAPER_USER. doPDF 8 почему-то картинку помещает справа и вертикально. Adobe PDF ухудшает изображения, впрочем этим и другие грешат, кроме Snagit.

Сейчас в примере печатается цветной файл. Как переключить на монохромный:
- в Connect Printer 2.vi задать dmColor=DMCOLOR_MONOCHROME;
- в кластере BITMAPV4HEADER основного :vi: задать bV4BitCount=1, bV4ClrUsed=2, bV4ClrImportant=2;
- в CreateDIBitmap CLFN на вход pBitmapInfo завести розовый провод с присоединённой ч/б палитрой (после Bundle);
- на вход pArrayOfBytes завести массив image с Unbundle, а не с Unflatten Pixmap.
В принципе, это всё. Я проверял, тоже работает.

Кстати, у меня и DLL'ки тоже заработали после того, как я изменил пару мелочей:
- закомментил dm->dmDriverExtra = 0; (не всем принтерам нравится, когда dmDriverExtra заигнорен; например, Adobe PDF выдавал ошибку при StartDoc).
- прописал изменённые поля в dm->dmFields (не все поля структуры учитывались при печати).
Можно ещё по желанию прописать dmScale, dmPaperSize и dmOrientation.
Думал выложить скомпилированные файлы, но наверное это ни к чему. Всё-таки на диаграмме проще код поменять, если возникнет необходимость. Для компиляции нужна студия, нужно учитывать разрядность и т.п.
PAG писал(а): 28 ноя 2023, 07:56Решил задачу на низком уровне: написал три функции на С++ с использованием GDI и сделал DLL.
С C# рисковать не стал: слишком много версий .NET расплодилось.
Хорошо, что разобрались, можно тогда и на этом остановиться. В таком случае, возможно, кому-то ещё пригодятся :vi: , выложенные выше. Насчёт .NET - думаю, правильное решение. Задача не самая сложная, тащить зависимость от фреймворка ни к чему. Хотя при инсталляции RTE он всё равно понадобится, но при явных зависимостях приложение будет дольше запускаться, станет тяжелее/прожорливее и может "тупить" временами, даже при корректно организованной архитектуре. Конечно, дотнет иногда необходим, если, например, используется какая-то сторонняя библиотека, от которой никуда не уйти. Но в большинстве случаев можно обойтись без него.
PAG писал(а): 26 ноя 2023, 18:16И вообще: если создавать DLL для среды LV, то какой язык программирования использовать?
Вообще, в любой среде можете создавать, если она способна компилировать нативные DLL/SO. Просто не используйте в качестве аргументов и возвращаемого значения типы, специфические для среды (например, классы), сложные структуры, иначе в :labview: не сможете с ними работать. Чем проще, тем лучше. Массивы и строки передавайте по ссылке, остальное можно по значению. Кстати, и в обратную сторону (из LV в DLL) тоже не передавайте ничего :labview: -специфичного, т.к. :labview: хранит данные не так, как другие IDE (см. How LabVIEW Stores Data in Memory), это касается массивов и строк, а также ссылок (reference), путей, variant'ов. Если надо передать массив/строку, передайте указатель на данные. Указатели-параметры передавайте как Unsigned Pointer-sized Integer. В принципе, есть возможность работать с типами :labview: из библиотеки при подключении extcode.h, но это довольно редко бывает нужно, современные версии :labview: неплохо оптимизированы и выносить какой-то код во внешнюю библиотеку обычно не требуется.
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

dadreamer, в твоем примере Print Test 3.vi используются функции из gdi32.dll.
Это будет корректно работать в LV x64 на платформе x64, или надо что-то заменять?
Наверняка у принтера драйвер установлен для целевой платформы, и если она x64, то и драйвер такой же.
Тут не будет конфликта?
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3939
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 12 раз
Поблагодарили: 133 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение dadreamer »

PAG писал(а): 11 июн 2024, 11:41dadreamer, в твоем примере Print Test 3.vi используются функции из gdi32.dll.
Это будет корректно работать в LV x64 на платформе x64, или надо что-то заменять?
Наверняка у принтера драйвер установлен для целевой платформы, и если она x64, то и драйвер такой же.
Тут не будет конфликта?
Не будет и ничего менять не нужно. На 64-битной Windows системные библиотеки для 64-битных программ тянутся из \System32 и они там все 64-битные. Для 32-битных программ библиотеки тянутся из \SysWOW64, там лежат аналогичные версии библиотек, но 32-битные. Windows сама определяет, какие именно библиотеки нужны запускаемой программе. Циферка "32" в имени DLL - это по большей части для обратной совместимости, чтобы чужие приложения не поломались.

Вчера я также пробовал запускать пример на Windows 10 64-bit и :labview: 2024 Q1 64-bit, сделал пару распечаток на виртуальном принтере. Всё в порядке.
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

dadreamer, я сделал проектик на базе твоих примеров, который открывает принтер и подсовывает ему указанный битмапчик.
У меня битмапы монохромные, и принтер печатает их квадратами Малевича, т.е затушевывает всю картинку.
Подскажи, плз, что надо переключить в твоих модулях для монохромной картинки?
Примерчик изначально подразумевает полноцветную картинку, и заголовок сразу готовит для таких изображений.
Я подозреваю, что как минимум надо изменить некоторые поля в заголовке битмапа, или взять их из считанного заголовка, но боюсь накосячить. У меня картинки всегда монохромные.
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3939
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 12 раз
Поблагодарили: 133 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение dadreamer »

Попробуйте вот этот вариант.
Вложения
printer test 3.vi
lv2019
(20.48 КБ) 5 скачиваний
Connect Printer 2.vi
lv2019
(31.94 КБ) 4 скачивания
PAG
junior
junior
Сообщения: 58
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 10 раз
Поблагодарили: 3 раза
Контактная информация:

Re: В какой среде (CPP/C#) может быть написана DLL, которую предполагается вызывть из среды LV?

Сообщение PAG »

Не помогло. :think: Я оказался не прав: картинка у меня была монохромная давно тому назад. Давно не лазил в эту процедуру, стал забывать.
Сейчас я отрисовываю ее на окне через Image с серой палитрой и записываю в файл через "Write BMP File.vi" (см. прицеп).
В результате получаю RGB файл с 8 бит на пиксел. Черная она только внешне.
Возможно, мне не стоит "ломать копья, и просто изменить формат создаваемого файла на полноцветный?
Но файл размером с печатный лист будет довольно большого размера. Это, конечно, пустяки, но как-то не очень хочется.
Прицепляю тестовую картинку и результат ее печати последней версией Вашей утилиты.
Возможно, будет проще изменить параметры создаваемой картинки в процедуре ее записи, изменив глубину цветности?
Вложения
Результат печати
Результат печати
Printer.png (2.51 КБ) 142 просмотра
процедура записи файла картинки
процедура записи файла картинки
WriteImage.png (5.83 КБ) 142 просмотра
Параметры файла картинки
Параметры файла картинки
ImageParams.png (10.24 КБ) 142 просмотра
Тестовая картинка (реально *.bmp)
Тестовая картинка (реально *.bmp)
Report.png (930 байт) 121 просмотр
Последний раз редактировалось PAG 21 июн 2024, 15:32, всего редактировалось 3 раза.
Ответить
  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Для чайников»