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

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

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

Сообщение PAG »

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

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

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

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

Сообщение dadreamer »

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

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

Сообщение PAG »

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

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

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

Сообщение dadreamer »

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

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
Сообщения: 3925
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 11 раз
Поблагодарили: 126 раз
Контактная информация:

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
beginner
beginner
Сообщения: 48
Зарегистрирован: 27 ноя 2020, 15:51
Версия LabVIEW: 19
Благодарил (а): 8 раз
Контактная информация:

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

Сообщение PAG »

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

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

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

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

Сообщение PAG »

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

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

Сообщение PAG »

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

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

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

Сообщение dadreamer »

Некогда было этим заниматься, да и там, как оказалось, чуть больше времени потребовалось для переноса на БД. Кластеры, конечно, громоздкие, но с этим ничего не сделать. Можно оформить в SubVI, мне просто лень, два я сделал, на этом закончил.
printer test 3.vi
lv2019
(22.16 КБ) 18 скачиваний
Connect Printer 2.vi
lv2019
(30.32 КБ) 24 скачивания
Close Printer.vi
lv2019
(11.08 КБ) 20 скачиваний
Проверял как в 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: неплохо оптимизированы и выносить какой-то код во внешнюю библиотеку обычно не требуется.
Ответить
  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

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