Call library function node
Call library function node
Вызываю функцию из сторонней dll. В принципе всё работает, но есть неясности, как. Перерыл весь хелп на тему. Вот на конкретном примере:
Функция (конвенция __stdcall) возвращает указатель на строку, а принимает 1 параметр, это указатель на unsigned long int (то есть в адрес по этому указателю она также выводит некоторое значение). В меню Configure всё настроил соотв. образом, "String format" - C string pointer, а для передаваемого параметра "Pass" - Pointer to value. Готовый вид узла на скрине. Вот собсно вопросы.
1) С выходного терминала узла уже передаётся сама строка, а не указатель, то есть, как я понял, автоматически считывает строку по адресу, который выдала функция? А если я хочу далее манипулировать именно с самим указателем? И где найти функции для работы с указателями (pointers), то есть получение указателя, чтение данных из указателя? Не нашёл в хелпе.
2) Теперь про параметр. По идее, я вначале должен получить указатель на какую-то 4-байтовую переменную, а затем этот указатель подключить к левому терминалу (и далее считывать с правого напротив), но всё работает, если ничего не подключать. Это корректный способ? Что тогда делает , просто создаёт где-то в памяти область нужного размера (4 байт в данном случае), и использует её при этой операции?
3) Чем отличаются настройки Run in UI thread / Run in any thread? Из названия понятно, что "работает либо в потоке польз. интерфейса, либо в любом потоке", но в чём её смысл? По идее должно работать в том потоке, из которого я вызвал сабж. В хелпе как-то мутно написано. Если не трудно, объясните по-человечески.
Функция (конвенция __stdcall) возвращает указатель на строку, а принимает 1 параметр, это указатель на unsigned long int (то есть в адрес по этому указателю она также выводит некоторое значение). В меню Configure всё настроил соотв. образом, "String format" - C string pointer, а для передаваемого параметра "Pass" - Pointer to value. Готовый вид узла на скрине. Вот собсно вопросы.
1) С выходного терминала узла уже передаётся сама строка, а не указатель, то есть, как я понял, автоматически считывает строку по адресу, который выдала функция? А если я хочу далее манипулировать именно с самим указателем? И где найти функции для работы с указателями (pointers), то есть получение указателя, чтение данных из указателя? Не нашёл в хелпе.
2) Теперь про параметр. По идее, я вначале должен получить указатель на какую-то 4-байтовую переменную, а затем этот указатель подключить к левому терминалу (и далее считывать с правого напротив), но всё работает, если ничего не подключать. Это корректный способ? Что тогда делает , просто создаёт где-то в памяти область нужного размера (4 байт в данном случае), и использует её при этой операции?
3) Чем отличаются настройки Run in UI thread / Run in any thread? Из названия понятно, что "работает либо в потоке польз. интерфейса, либо в любом потоке", но в чём её смысл? По идее должно работать в том потоке, из которого я вызвал сабж. В хелпе как-то мутно написано. Если не трудно, объясните по-человечески.
- Вложения
-
- Безымянный.png (2.11 КБ) 7894 просмотра
Race conditions - опасный и скользкий баг!
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Call library function node
Да, и автоматически конвертирует во внутренний тип LStr, потому что C String и LabVIEW String - это разные вещи.автоматически считывает строку по адресу, который выдала функция?
Плохо представляю, зачем это нужно, кроме узкоспециализированных манипуляций. Но если все-таки нужно, то делаете возвращаемое значение как Unsigned Pointer-Sized Integer. Считать из указателя / записать по нему можно с помощью функции MoveBlock: https://decibel.ni.com/content/docs/DOC-9091 Работа с памятью в выполняется с помощью функций менеджера памяти (DSNewPtr и т.д.): http://zone.ni.com/reference/en-XX/help ... functions/ (это есть и во встроенной справке ). Обычно эти функции используются во внешнем коде, однако можно и вызывать их из самого .А если я хочу далее манипулировать именно с самим указателем? И где найти функции для работы с указателями (pointers), то есть получение указателя, чтение данных из указателя?
Да, хотя я предпочитаю засылать туда 0, так при отключении правого провода, левый терминал остается определенным, а не пустым (void). LabVIEW делает так, как вы написали.Это корректный способ? Что тогда делает , просто создаёт где-то в памяти область нужного размера (4 байт в данном случае), и использует её при этой операции?
UI поток в один, в нём работают все графические элементы панели (кнопки, контролы, индикаторы и т.д.). Если у вас вызов библиотеки будет в UI потоке и по какой либо причине затянется/зависнет, то это подвесит всю программу, т.к. поток UI будет заблокирован. Это событие на самом деле редкое, т.к. его стараются избежать при разработке DLL, делая её функции реентерантными. Опцию работы в UI потоке в узле CLFN оправдано ставить только тогда, когда не предполагается параллельная работа одних и тех же функций из библиотеки. В противном случае нужно ставить Run in any thread для параллельного вызова, но вы должны точно знать, что разработчик DLL сделал эти функции реентерантными.Чем отличаются настройки Run in UI thread / Run in any thread?
Re: Call library function node
Параллельная в рамках данного приложения, или учитывая, что эта биб-ка может использоваться другими приложениями? В моём приложении предполагается только последовательный вызов, и из одного потока. Но есть другая программа, которая тоже запущена и юзает эту биб-ку...Опцию работы в UI потоке в узле CLFN оправдано ставить только тогда, когда не предполагается параллельная работа одних и тех же функций из библиотеки.
Race conditions - опасный и скользкий баг!
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Call library function node
В рамках одного процесса, в конкретном случае - вашей программы. Если используется одновременно в другой программе, то это косвенно говорит о том, что функции потокобезопасны. В вашем случае, получается, по барабану, что ставить - UI или Any Thread.
Re: Call library function node
А как в данном случае интерпретируется нулевой адрес?Да, хотя я предпочитаю засылать туда 0, так при отключении правого провода, левый терминал остается определенным, а не пустым (void).
Race conditions - опасный и скользкий баг!
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Call library function node
Boris_K, это не NULL, это начальное состояние переменной при передаче её в функцию. В большинстве случаев без разницы, что туда посылать, можно любое число прописать. Так как в CLFN стоит Pass - Pointer To Value, то всё равно перезапишет эту область памяти значением, полученным при вызове функции. Нюанс есть тогда, когда функция работает сразу с начальным состоянием переменной. Например,
В данном случае состояние переменных *a и *b важно, так как они являются слагаемыми. А вот результат суммирования *sum перезаписывается.
Код: Выделить всё
void MyFunc(int32 *a, int32 *b, int32 *sum)
{
*sum = *a + *b;
}
-
- junior
- Сообщения: 52
- Зарегистрирован: 23 мар 2015, 18:29
- Версия LabVIEW: 2010
- Контактная информация:
Re: Call library function node
Здравствуйте, а у меня возник следующий вопрос при использовании этого vi: в параметрах функции есть тип enum, а также есть структура - как их указать в параметрах labview, какой применить тип?
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Call library function node
1. enum зависит от параметров компилятора, как правило это обычный int (I32), если не указано иное. Сопоставлять конкретный enum и число следует по заголовочному (*.h) файлу, где дано определение этого enum'а;danya писал(а):Здравствуйте, а у меня возник следующий вопрос при использовании этого vi: в параметрах функции есть тип enum, а также есть структура - как их указать в параметрах labview, какой применить тип?
2. структура (struct) может передаваться в функцию в виде кластера; в таком случае нужно выставить в CLFN опцию Adapt To Type - Handles By Value, в результате кластер будет передан по ссылке (т.е., передаётся не сам кластер со всеми "потрохами", а указатель на него). Если структура сильно сложная и не может быть выражена на БД в виде кластера, то можно передавать блок памяти или массив U8. Иногда функция требует инициализации входных параметров, тогда в этот блок данных следует прописать начальные значения. После вызова функции придётся преобразовать блок данных в удобный для LV вид.
- Favorit
- interested
- Сообщения: 4
- Зарегистрирован: 09 дек 2016, 19:22
- Версия LabVIEW: 8-15
- Контактная информация:
Re: Call library function node
Приветствую всех, возник вопрос по Call library function node.
Есть библиотека с соглашением о вызове cdecl в заголовочном файле есть функция, принимает параметр типом указателя на функцию:
имя типа данных объявлена так:
Сделал так
Есть библиотека с соглашением о вызове cdecl в заголовочном файле есть функция, принимает параметр типом указателя на функцию:
Код: Выделить всё
MOTO_DLL_2_API int _cdecl AddParamToStream(int inv,char *name,READ_CALLBACK onPoint);
Код: Выделить всё
typedef void (__stdcall *READ_CALLBACK)(int, int, double, void *, int);
но при передаче пустого кластера LabView выдаёт ошибку, может кто подскажет....структура (struct) может передаваться в функцию в виде кластера; в таком случае нужно выставить в CLFN опцию Adapt To Type - Handles By Value
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Call library function node
Favorit, не используйте пока [ code ], на форуме проблемы с его отображением.
[q=="Favorit"]Приветствую всех, возник вопрос по Call library function node.
Есть библиотека с соглашением о вызове cdecl в заголовочном файле есть функция, принимает параметр типом указателя на функцию:
MOTO_DLL_2_API int _cdecl AddParamToStream(int inv,char *name,READ_CALLBACK onPoint);
имя типа данных объявлена так:
typedef void (__stdcall *READ_CALLBACK)(int, int, double, void *, int);
Сделал так
[q=="dadreamer"]структура (struct) может передаваться в функцию в виде кластера; в таком случае нужно выставить в CLFN опцию Adapt To Type - Handles By Value[/q]
но при передаче пустого кластера LabView выдаёт ошибку, может кто подскажет....[/q]
Вам нужно передать указатель на функцию, почему вы решили передать структуру? Где у вас находится этот колбэк? Он должен быть написан, чтобы передать его адрес. Обычно подобные вещи нужно писать программисту в традиционной среде программирования в виде DLL. Хотя, возможно, разработчик предоставил какие-то стандартные функции для этого?..
[q=="Favorit"]Приветствую всех, возник вопрос по Call library function node.
Есть библиотека с соглашением о вызове cdecl в заголовочном файле есть функция, принимает параметр типом указателя на функцию:
MOTO_DLL_2_API int _cdecl AddParamToStream(int inv,char *name,READ_CALLBACK onPoint);
имя типа данных объявлена так:
typedef void (__stdcall *READ_CALLBACK)(int, int, double, void *, int);
Сделал так
[q=="dadreamer"]структура (struct) может передаваться в функцию в виде кластера; в таком случае нужно выставить в CLFN опцию Adapt To Type - Handles By Value[/q]
но при передаче пустого кластера LabView выдаёт ошибку, может кто подскажет....[/q]
Вам нужно передать указатель на функцию, почему вы решили передать структуру? Где у вас находится этот колбэк? Он должен быть написан, чтобы передать его адрес. Обычно подобные вещи нужно писать программисту в традиционной среде программирования в виде DLL. Хотя, возможно, разработчик предоставил какие-то стандартные функции для этого?..
- Favorit
- interested
- Сообщения: 4
- Зарегистрирован: 09 дек 2016, 19:22
- Версия LabVIEW: 8-15
- Контактная информация:
Re: Call library function node
[quote=="dadreamer"]
Вам нужно передать указатель на функцию, почему вы решили передать структуру? Где у вас находится этот колбэк? Он должен быть написан, чтобы передать его адрес. Обычно подобные вещи нужно писать программисту в традиционной среде программирования в виде DLL. Хотя, возможно, разработчик предоставил какие-то стандартные функции для этого?..[/quote]
dll библиотека иметься, для этой библиотеки имеется *.h с описанием функций, библиотеку импортировал с помощью инструмента Import->Shared Library (dll)...
Почти все функции импортировались нормально кроме одной AddParamToStream, в качестве праметра предаётся переманная onPoint типом READ_CALLBACK тип является указателем на функцию.
Shared Library (dll)... автоматически принял настройки Adapt To Type - Handles By Value по праметру onPoint, Call library function node принимает на этот вход пустой кластер, и выдаёт ошибку на эту связь
это фрагмент *.h
typedef void (__stdcall *READ_CALLBACK)(int, int, double, void *, int);
MOTO_DLL_2_API int _cdecl AddParamToStream(int inv,char *name,READ_CALLBACK onPoint);
Вам нужно передать указатель на функцию, почему вы решили передать структуру? Где у вас находится этот колбэк? Он должен быть написан, чтобы передать его адрес. Обычно подобные вещи нужно писать программисту в традиционной среде программирования в виде DLL. Хотя, возможно, разработчик предоставил какие-то стандартные функции для этого?..[/quote]
dll библиотека иметься, для этой библиотеки имеется *.h с описанием функций, библиотеку импортировал с помощью инструмента Import->Shared Library (dll)...
Почти все функции импортировались нормально кроме одной AddParamToStream, в качестве праметра предаётся переманная onPoint типом READ_CALLBACK тип является указателем на функцию.
Shared Library (dll)... автоматически принял настройки Adapt To Type - Handles By Value по праметру onPoint, Call library function node принимает на этот вход пустой кластер, и выдаёт ошибку на эту связь
это фрагмент *.h
typedef void (__stdcall *READ_CALLBACK)(int, int, double, void *, int);
MOTO_DLL_2_API int _cdecl AddParamToStream(int inv,char *name,READ_CALLBACK onPoint);
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Call library function node
Import Shared Library Wizard не достаточно интеллектуален, чтобы различать некоторые сложные типы данных, кроме того он не поддерживает многие фичи C++, например указатель на this и классы. Если не планируете пользоваться этой функцией, то попробуйте исключить её из импорта - снимите галку на её имени. Если же очень сильно нужна эта функция, то вам придётся подкорректировать настройки CLFN вручную. Этот последний параметр должен быть в виде Numeric -> Unsigned Pointer-Sized Integer. А чтобы вызвать AddParamToStream, нужно иметь кастомную (самописную) функцию-колбэк в некоторой DLL. Далее парой функций LoadLibrary/GetModuleHandle + GetProcAddress получаете адрес вашего колбэка и передаёте в AddParamToStream. Естественно, внутри callback должна находиться какая-то простенькая логика, например, передача значений в через PostLVUserEvent.
- Favorit
- interested
- Сообщения: 4
- Зарегистрирован: 09 дек 2016, 19:22
- Версия LabVIEW: 8-15
- Контактная информация:
Re: Call library function node
[quote=="dadreamer"]Подкорректировать настройки CLFN вручную. Этот последний параметр должен быть в виде Numeric -> Unsigned Pointer-Sized Integer. А чтобы вызвать AddParamToStream, нужно иметь кастомную (самописную) функцию-колбэк в некоторой DLL. Далее парой функций LoadLibrary/GetModuleHandle + GetProcAddress получаете адрес вашего колбэка и передаёте в AddParamToStream. Естественно, внутри callback должна находиться какая-то простенькая логика, например, передача значений в через PostLVUserEvent.[/quote]
Пока ещё не сталкивался LoadLibrary/GetModuleHandle + GetProcAddress
Решил проблему передаче кластера типа Variant... Если понадобиться функция попробую ваш вариант, спасибо !
Пока ещё не сталкивался LoadLibrary/GetModuleHandle + GetProcAddress
Решил проблему передаче кластера типа Variant... Если понадобиться функция попробую ваш вариант, спасибо !
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
- 1 Ответы
- 1029 Просмотры
-
Последнее сообщение Artem.spb
-
- 8 Ответы
- 686 Просмотры
-
Последнее сообщение Select
-
- 8 Ответы
- 2028 Просмотры
-
Последнее сообщение Eugene_Eugene