|
![]() |
#1 |
Участник
|
Дескриптор или как получить Handle функции из dll компоненты
Имеется пример написанный на языке C#, так же есть ИС Axapta 3.0.
В примере сначала по коду создают объект функции и получают дескриптор handle Пример из C# public partial class FormMain : Form { IntPtr m_server; int m_port; BindingList<TcpTerminal> m_terminals; int m_alertcount=0; const int WM_APP=0x8000; const int MAXSNSIZE=256; const int MAXFIELDSIZE=256; public FormMain() { InitializeComponent(); m_server=IntPtr.Zero; m_port=1024; m_terminals=new BindingList<TcpTerminal>(); listBoxTerminals.DataSource=m_terminals; listBoxTerminals.DisplayMember="SerialNumber"; comboBoxMessageType.SelectedIndex=0; buttonMessageSend.Enabled=false; buttonMessageSendAll.Enabled=false; buttonSendAnswer.Enabled=false; UpdateBottomControls(); } получение Handle: private void buttonStartStop_Click(object sender,EventArgs e) { int res; if(m_server==IntPtr.Zero) { res=cipherlabtcpCreate(ref m_server); } } в переменной m_server формируется ссылка (дескриптор), который дальше участвует в программном коде Проблема заключается в том, как перевести C# на программный код X++ и получить ссылку Handle? Первоначально m_server обозначают как IntPtr, но в X++ (Axapta) такого нет, так как нет в x++ встал вопрос как инициализировать m_server? в примере на C# инициализируют как m_server=IntPtr.Zero (дескриптор, инициализированный с нулевым значением.) Подскажите пожалуйста как можно получить дескриптор в x++ Axapta согласно куска примера на C#?
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#2 |
Участник
|
А зачем нужно переделывать C# код на Х++ для 3.0? По-моему, проще будет сделать обертку на C# и дергать ее из 3.0 через COM. Я лично делал примерно так:
|
|
|
За это сообщение автора поблагодарили: AlexSt (1). |
![]() |
#3 |
Участник
|
Просто есть dll компонента для подключения Wi-Fi ТСД в ней организованы Native функции, к компоненте есть пример на C#, по этому примеру идет подключение к компоненте dll и обращения к определенным функциям компоненты. Но в примере чтобы подключить нужно получить дескриптор handle функции для подключения и затем применять его везде (передача + приём данных в AX)
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#4 |
Участник
|
Вот что в Аксапте получилось
X++: static void Job77(Args _args) { Int // Номер порта Int // Результат int // Метод записи int // Отладка Int // Номер ошибки void void void void int Binary Counter // Номер БД в ТСД всего их 3 Counter // Номера форм в ТСД всего их 8мь M583_ImportedData Int Binary Binary Binary Binary Binary Binary Binary Binary DLL // Драйвер терминала (CipherLabTCP.dll) DLLFunction // Подключить (cipherlabtcpStart) DLLFunction // Отключить (cipherlabtcpStop) DLLFunction // Инициализация компоненты объекта сервера (cipherlabtcpCreate) DLLFunction // Получение строки события в обработчике события (cipherlabtcpGetEvent) DLLFunction // Устанавливает callback функцию для события от ТСД (cipherlabtcpSetEventCallback) DLLFunction // Задание оконного сообщения для события (cipherlabtcpSetEventMassega) DLLFunction // Удаленее ранее созданного объекта сервера (cipherlabtcpDestroty) DLLFunction // Пинг (cipherlabtcpPing) DLLFunction // Получить данные (cipherlabtcpGetData) DLLFunction // Получить серийный номер ТСД (cipherlabtcpGetSerialNumber) DLLFunction // Послать ответ на ТСД (cipherlabtcpAnswer) DLLFunction // Получить параметры с ТСД (cipherlabtcpGetProperties) DLLFunction // Назначить параметры ТСД (cipherlabtcpSetPropierties) DLLFunction // Послать сообщение на ТСД без вибро сигнала (cipherlabtcpSendMessage) DLLFunction // Послать предупреждение на ТСД с вибро сигналом и миганием свет диода (cipherlabtcpSendWarning) CipherLabTCP = new DLL("CipherLabTCP") // Драйвер терминала GetProperties = new DLLFunction(CipherLabTCP, 'cipherlabtcpGetProperties') // Получение параметров SetProperties = new DLLFunction(CipherLabTCP, 'cipherlabtcpSetProperties') // Назначение параметров Enable = new DLLFunction(CipherLabTCP, 'cipherlabtcpCreate') // Инициализация компоненты объекта сервера Attach = new DLLFunction(CipherLabTCP, 'cipherlabtcpStart') // Запуск сервера Deattach = new DLLFunction(CipherLabTCP, 'cipherlabtcpStop') // Остановка сервера Destroy = new DLLFunction(CipherLabTCP, 'cipherlabtcpDestroy') // Освобождение ресурсов SetEventCallback = new DLLFunction(CipherLabTCP, 'cipherlabtcpSetEventCallback') // Устанавливает callback функцию для события от ТСД GetEvent = new DLLFunction(CipherLabTCP, 'cipherlabtcpGetEvent') // Получение строки события GetDataSN = new DLLFunction(CipherLabTCP, 'cipherlabtcpGetSerialNumber') // Получить серийный номер ТСД Port = SaveMethod = Debug = Enable.returns(ExtTypes::void) Enable.arg(ExtTypes::void) ErrorNumber = Enable.call(ptrtohandle) if (ErrorNumber == 0) { SetEventCallback.returns(ExtTypes::void) SetEventCallback.arg(ExtTypes::void, ExtTypes::void, ExtTypes::void) ErrorNumber = SetEventCallback.call(ptrtohandle, callbackfunc, param1) GetProperties.returns(ExtTypes::void) GetProperties.arg(ExtTypes::void, ExtTypes::void, ExtTypes::void, ExtTypes::void) ErrorNumber = GetProperties.call(ptrtohandle, Port, SaveMethod, Debug) SetProperties.returns(ExtTypes::void) SetProperties.arg(ExtTypes::void, ExtTypes::void, ExtTypes::void, ExtTypes::void) ErrorNumber = SetProperties.call(ptrtohandle, Port, SaveMethod, Debug) Attach.returns(ExtTypes::void) Attach.arg(ExtTypes::void) ErrorNumber = Attach.call(ptrtohandle) if (ErrorNumber != 0) { Deattach.returns(ExtTypes::DWord) Deattach.arg(ExtTypes::void) Deattach.call(ptrtohandle) Destroy.returns(ExtTypes::DWord) Destroy.arg(ExtTypes::void) Destroy.call(ptrtohandle) warning ("Не удалось подключиться. Переподключите ТСД к WiFi") } } else { Deattach.returns(ExtTypes::DWord) Deattach.arg(ExtTypes::void) Deattach.call(ptrtohandle) Destroy.returns(ExtTypes::void) Destroy.arg(ExtTypes::void) Destroy.call(ptrtohandle) warning ("Не удалось подключиться. Переподключите ТСД к WiFi") } }
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#5 |
Участник
|
как в данном случае можно получить дескриптор в функции Enable dll библиотеки CipherLabTCP.dll на языке X++?
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#6 |
Участник
|
Как в аксапте можно сделать такую вещь:
IntPtr m_server, где IntPtr определяемый платформой тип, который используется для представления указателя или дескриптора, как можно представить в X ++ IntPtr?
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#7 |
Участник
|
X++: int i = 5; System.IntPtr IntPtr = new System.IntPtr(i); |
|
![]() |
#8 |
Участник
|
Делаю так
int i = 5; System.IntPtr IntPtr = new System.IntPtr(i); Пишет что Таблица не содержит это поле и курсор мигает перед System. В чем может быть проблема?
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#9 |
Участник
|
Посмотрите, как реализован вызов, к примеру, WinAPI::getComputerName() - там по ссылке передается DWORD, куда вызываемая функция записывает длину строки с названием компьютера. Обратите внимание, что тип аргументов функции указываются как ExtTypes::Pointer.
|
|
![]() |
#10 |
Участник
|
А ещё где можно посмотреть как в Аксапте 3.0 получить дескриптор файла из функции библиотеки dll? А так же как можно представить IntPtr в Аксапте 3.0
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#11 |
Участник
|
Я хотел бы ещё поинтересоваться, как можно построить в Axapta 3.0 указатель на дескриптор? Дескриптор имеет значение Void
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#12 |
Участник
|
Цитата:
Цитата:
Цитата:
Цитата:
Сообщение от ShkipeRR
![]() Появилась возможность спрограммировать отдельное приложение-сервис на основе компоненты CipherLabTCP.dll. как будет лучше принять данные с программы сервис и отправить обратное сообщение программе сервис, чтобы в дальнейшем сервис программа отослала это сообщение на дисплей ТСД (двунаправленная связь)?
PS. Хотя уже слабо верится, что на решение реальной задачи кто-то может отвести столько времени... Последний раз редактировалось gl00mie; 12.03.2014 в 10:40. Причина: PS |
|
![]() |
#13 |
Участник
|
Это реальная задача, только вот никак не получается подключится к компоненте, из примера смотришь вроде легко, для аксапты сложновато. в ступор сразу ввел указатель на дескриптор, а точнее создаем объект функцией cipherlabtcpCreate и получаем дескриптор сервера-
компоненты handle. никак не получается этот дескриптор Handle получить в аксапте 3.0. в примере этот дескриптор при обращении к функции cipherlabtcpCreate получается сразу 8 знаков в аксапте он получается 0. в результате автоматическое подключение к ТСД не происходит.
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#14 |
Участник
|
Ничего не получается с WinAPI будет программироваться отдельная программа для соединения ТСД с Аксаптой, будущая программа-сервис будет выполнять следующее:
1. Автоматически запускаться в виде сервиса, если программа-сервис дала сбой, то автоматически перезапускаться (при запуске происходит подключение к ТСД, если ТСД проявил активность); 2. После того как программа сервис была запущена на сервере, программа – сервис должна ожидать данные от терминалов сбора данных; 3. Как только какой-то терминал сбора данных проявит свою активность в функции-обработчике сначала нужно узнать тип события. Всего может быть 5 типов событий от ТСД: MAKE, CLOSE, QUERY, INSERT, UPDATE; 4. Выяснить серийный номер ТСД, который вызвал событие; 5. Получить данные из ТСД вместе с серийным номером от ТСД; 6. Отправить полученные данные из ТСД в ИС Axapta; 7. Ожидать ответа от ИС Axapta по полученным данным из ТСД; - Если в течении 5 секунд ответа нет, то освободить ресурсы для приема следующих данные от ТСД; - Если в течении 5 секунд ответ в программу сервер пришёл, то: a) принять ответ от Axapta в программу-сервис; b) отправить полученный ответ на дисплей ТСД, который вызвал событие (по серийному номеру ТСД); c) Освободить ресурсы и ждать следующих данных от ТСД; По этому поводу я хотел бы узнать у форума какими способами лучше принимать данные из внешней программы - сервис в Axapta 3.0 и какими способами лучше передавать данные (обратный ответ) из Axapta 3.0 обратно внешней программы - сервис?
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#15 |
Участник
|
Помогите реализовать в аксапте следущее:
в библиотеке CipherLabTCP.dll имеется функция следующего типа: Наименование: GetProperties(SAFEARRAY **paParams, LONG * Result) Вх. данные: paParams – Двумерный массив из 3 элементов типа (VARIANT). Вых. Данные: 1 элемент — Порт; 2 элемент — (0 — писать в файл, 1 — генерировать внещнее событие); 3 элемент — (1 — выводить отладочную информацию, 0 — не выводить отладочеую информацию); Описание: Функция для получения свойств компоненты. Возвращаемое значение: В случае успеха возвращает в Result двойной указатель на SAFEARRAY, иначе 0 Как можно изобразить это в аксапте 3.0? Как я думаю нужно организовать двумерный массив из 3 элемента, но не знаю как это будет выглядеть на языке X ++, помогите разобраться?
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#16 |
Banned
|
Цитата:
![]() Феерично. По крайней мере, автор перешел к активным действиям, т.е. программированию. Автор хочет соорудить что-то вроде listener, для чего на мой взгляд дилетанта разумнее всего было бы запрограммировать отдельный компонент ActiveX, встроить в форму AX 3.0 и подключить event-ы к коду X++. Последний раз редактировалось EVGL; 21.03.2014 в 19:21. |
|
![]() |
#17 |
Участник
|
В 3.0 нет никаких IntPtr; дескриптор, вероятнее всего, имеет тип не void, а void*. В данном случае при вызове функции cipherlabtcpCreate() нужно передать указатель на область памяти размером в 4 байта, куда функция запишет дескриптор - некое значение, имеющее смысл для других API-функций CipherLabTCP. Затем полученный дескриптор надо будет, вероятнее всего, по значению (а не по ссылке) передавать в прочие API-функции CipherLabTCP.
Пример того, как правильно через DLLFunction описать API-функцию, принимающую указатель в качестве параметра, и как потом получить записанное функцией значение, можно найти в WinAPI::getComputerName(). Что именно не получается с этим примером? PS. Описывать через DLLFunction, будто бы функция cipherlabtcpCreate() вообще не принимает на вход параметров (ExtTypes::void), в корне неверно. Тип void* означает "нетипизированный указатель" и с ExtTypes::void он не имеет ничего общего; указатель в терминах DLLFunction - это ExtTypes::Pointer. Последний раз редактировалось gl00mie; 04.03.2014 в 11:59. Причина: PS |
|
![]() |
#18 |
Участник
|
с void* всё верно. Описание функции нашёл
Название: int cipherlabtcpCreate(void** ptrtohandle) Входные параметры: - ptrtohandle (OUT) - указатель на дескриптор сервера-компоненты (дескриптор имеет тип void*), который используется в последующих вызовах, может быть равен NULL. Значение дескриптора должно быть инициализировано NULL. Выходные параметры: код ошибки Описание: Инициализация компоненты-объекта сервера .Создается объект-сервера. Если ptrtohandle равен NULL, подразумевается использование одной "глобальной" компоненты-сервера.
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#19 |
Участник
|
gl00mie
Как я понимаю если указатель на дескриптор, то нужно пользоваться ExtTypes::Pointer, а если входной параметр Int, то тут нужно задавать как ExtTypes: ![]()
__________________
Axapta 3.0 SP6 Build 1951 |
|
![]() |
#20 |
Участник
|
Скажем так, если в качестве входного параметра API-функции нужно передать ссылку на область памяти, куда функция будет что-то писать, либо указатель на структуру данных, которую нужно сформировать из X++ с учетом того, что там нет работы с указателями, то надо указывать тип параметра ExtTypes::Pointer. В этом случае DLLFunction поймет, что соответствующий параметр, переданный из X++, надо передать дальше по ссылке. Если же параметр API-функции - просто значение некоего указателя (const void*), которое вызывающий код X++ получает извне, то для DLLFunction тип такого параметра можно указать как ExtTypes::DWord и передавать соотв. значение указателя как целое число.
|
|
|
За это сообщение автора поблагодарили: Logger (5), ShkipeRR (1). |