gifts2017

Компилирование внешней компоненты AddInNative в ОС Linux

Опубликовал q_i в раздел Программирование - Внешние компоненты

В статье отражены некоторые моменты, которые нужно учесть, чтобы скомпилировать пример 1С-вской внешней компоненты AddInNative в ОС Linux.

Решил посмотреть, как работает внешняя компонента для 1С в Linux-е, благо под рукой уже была настроенная виртуалка с Xubuntu и установленной там платформой 8.3.5.1383.

Скопировал в виртуалку с диска ИТС папку VNCOMP83/example/NativeAPI/, зашёл в эту папку, набрал команду "make" и:

$ make

In file included from AddInNative.cpp:15:0:
AddInNative.h:4:27: фатальная ошибка: ComponentBase.h: Нет такого файла или каталога
компиляция прервана.
make: *** [AddInNative.o] Ошибка 1

Посмотрел, где расположен файл ComponentBase.h - как оказалось, он (и ряд других заголовочных файлов) находится в папке VNCOMP83/include/.

Вывод 1: с диска ИТС нужно копировать 2 папки - VNCOMP83/example/NativeAPI/ и VNCOMP83/include/

Пробую скомпилировать ещё раз:

$ make

In file included from AddInNative.cpp:15:0:
AddInNative.h:73:5: ошибка: «HANDLE» не является именем типа
AddInNative.h:74:5: ошибка: «HANDLE» не является именем типа
...

make: *** [AddInNative.o] Ошибка 1

Действительно, в файле AddInNative.h в самом конце присутствуют следующие определения:

    HANDLE              m_hTimer;
    HANDLE              m_hTimerQueue;

Linux про тип HANDLE ничего не знает. Смотрю где используются m_hTimer и m_hTimerQueue - они используются в файле AddInNative.cpp - один раз в CAddInNative::CAddInNative(), ещё один раз в CAddInNative::Done() и, наконец, в CAddInNative::CallAsProc(...) в ветках "case eMethStartTimer" и "case eMethStopTimer". Причём в последней процедуре код, связанный с этими переменными, выделен как Windows-специфичный (#ifndef __linux__ ... #endif). Отсюда можно сделать вывод, что в других местах разработчики просто забыли выделить код с помощью директив. Сделаем это самостоятельно.

В AddInNative.h меняю:

    HANDLE              m_hTimer;
    HANDLE              m_hTimerQueue;

на

#ifndef __linux__
    HANDLE              m_hTimer;
    HANDLE              m_hTimerQueue;
#endif

В AddInNative.cpp меняю:

CAddInNative::CAddInNative()
{
    m_iMemory = 0;
    m_iConnect = 0;
    m_hTimerQueue = 0;
}

на

CAddInNative::CAddInNative()
{
    m_iMemory = 0;
    m_iConnect = 0;
#ifndef __linux__
    m_hTimerQueue = 0;
#endif
}

после чего

void CAddInNative::Done()
{
    if(m_hTimerQueue )
    {
        DeleteTimerQueue(m_hTimerQueue);
        m_hTimerQueue = 0;
    }
}

меняю на

void CAddInNative::Done()
{
#ifndef __linux__
    if(m_hTimerQueue )
    {
        DeleteTimerQueue(m_hTimerQueue);
        m_hTimerQueue = 0;
    }
#endif
}

Как вариант, можно просто закомментировать "linux-неугодный" код, но тогда исходники перестанут компилироваться под Windows.

Вывод 2: перед компилированием нужно убрать Windows-специфичный код из исходников.

Очередная попытка:

$ make

...

AddInNative.cpp:438:49: ошибка: нет подходящей функции для вызова «IMsgBox::Alert(const wchar_t [3])»
...

make: *** [AddInNative.o] Ошибка 1

Тут уже даже разбираться не хочется, поэтому просто в файле AddInNative.cpp в функции CAddInNative::CallAsProc() комментирую строки:

//                        if (succeed)
//                            imsgbox->Alert(L"OK");
//                        else
//                            imsgbox->Alert(L"Cancel");

Вывод 3: перед компилированием нужно убрать ещё кое-какой код.

И ещё раз:

$ CXXFLAGS="-D __linux__" make

...

g++ -MM -D __linux__ -I../include -m32 -finput-charset=WINDOWS-1251 -fPIC AddInNative.cpp >  AddInNative.d
g++ -c  -D __linux__ -I../include -m32 -finput-charset=WINDOWS-1251 -fPIC dllmain.cpp -o dllmain.o
g++ -MM -D __linux__ -I../include -m32 -finput-charset=WINDOWS-1251 -fPIC dllmain.cpp >  dllmain.d
g++ -c  -D __linux__ -I../include -m32 -finput-charset=WINDOWS-1251 -fPIC stdafx.cpp -o stdafx.o
g++ -MM -D __linux__ -I../include -m32 -finput-charset=WINDOWS-1251 -fPIC stdafx.cpp >  stdafx.d
g++ -D __linux__ -I../include -m32 -finput-charset=WINDOWS-1251 -fPIC -shared AddInNative.o dllmain.o stdafx.o -o AddInNative.so -lpthread

Аллилуйя!!! Наконец-то, в каталоге появился долгожданный AddInNative.so!!!

Теперь попробую подключить эту внешнюю компоненту. Создаю новую внешнюю обработку, добавляю на форму команду Команда1 и пишу обработчик:

&НаСервере
Процедура Команда1НаСервере()

	Ок = ПодключитьВнешнююКомпоненту("/путь/к/файлу/внешней/компонеты/AddInNative.so", "AddInNative", ТипВнешнейКомпоненты.Native);
	Если НЕ Ок Тогда
		Сообщение = Новый СообщениеПользователю;
		Сообщение.Текст = "Ошибка подключения ВК!";
		Сообщение.Сообщить();
		Возврат;
	КонецЕсли;

	ОбъектВК = Новый("AddIn.AddInNative.AddInNativeExtension");
	ДвДанные = ОбъектВК.ЗагрузитьКартинку("/usr/share/backgrounds/space-01.jpg");
	Сообщение = Новый СообщениеПользователю;
	Сообщение.Текст = "Прочитано байт: " + ДвДанные.Размер();
	Сообщение.Сообщить();

КонецПроцедуры

&НаКлиенте
Процедура Команда1(Команда)

	Команда1НаСервере();

КонецПроцедуры

И она таки вертится:

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Константин Юрин (kostyaomsk) 15.01.15 08:09
Хоть и стороняя эта тема по разработке внешних компонент да еще в линуксе поставлю плюс.
2. Caponid V (caponid) 16.01.15 10:09
3. Роман Ложкин (webester) 17.01.15 11:53
(1)Очень ценное и нужное замечание, держите нас в курсе. Весь инфостарт испереживался, я сам как на иголках, нервы на пределе, обновляю страницу, каждые 15секунд, Внимание! Опасный момент! И да! Да дорогие друзья, kostyaomsk таки поставил плюс и оставил об этом комментарий. Как мы все долго этого ждали, этого бесполезного никому не нужного комментария "поставил +". И вот он наконец то! Спасибо тебе kostyaomsk за твой флуд ради флуда.
4. Андрей Ягодка (Yagodka.Andrey) 19.01.15 14:33
За статью спасибо, камрад.
Сейчас компоненты забросил, но... чем черт не шутит )
5. q_i 19.01.15 17:30
(4) Yagodka.Andrey, если будет интерес - можно будет попробовать скооперироваться.
И вообще, если у кого-нибудь есть какая-нибудь практическая задача - пишите - может что-нибудь сделаем. А то сейчас у меня весь интерес чисто академический (единственный клиент с линуксовым сервером перешёл на винду ещё год назад). ))
6. Мищенко Вадим (vslimv) 20.01.15 10:57
(5) q_i, Давно мечтаю о telnet'e на сервере. Правда в ВК дуб)
Но очень радостно, что подобные технологии развиваются, а то в моем окружении никто не решился на com в лине)
7. q_i 20.01.15 12:58
(6) vslimv, ну на com в лине не решился даже microsoft ))
А какую задачу хочется решить с помощь telnet'а на сервере?
8. Евгений Сосна (pumbaE) 20.01.15 13:22
sleep, добавь sleep
регулярки
поддрежку webcosket , дабы можно было-бы в тонком клиенте прогресс бар нарисовать.
rabbitmq
9. q_i 20.01.15 19:24
(8) pumbaE,
sleep:
ЗапуститьПриложение("sleep 5", , Истина);

Регулярки аналогично через perl/grep.

Вообще, есть мысль написать статью про вызов линуксовых команд из 1С. В простейшем варианте через ЗапуститьПриложение() с перенаправлением stdout во временный файл с последующим разгребанием этого файла средствами 1С. Но хочется ещё реализовать компоненту для работы без временного файла, т.е. вызывается команда и её stdout читается прямо в строку 1С (возможная опция - запись в stdin). В примитивном варианте это можно сделать в компоненте через popen(), в более продвинутом через pipe()/fork()/exec(). Собственно, и статья родилась когда решил попробовать реализовать эту простенькую задачку и начал компилить сырцы 1с. Впрочем, popen() чего-то не захотел тогда работать (fread() сразу же возвращал 0, а feof(), соответственно, 1).

WebSocket и RabbitMQ - а что с ними делать? )))
10. Кикос Одинэсенко (servs) 21.01.15 12:33
(7) q_i, например для управления Asterisk используя AMI, нужен клиент telnet.
Есть ROM-Asterisk-Native, но там закрытый код.
11. q_i 21.01.15 13:14
(10) servs, я Пастернака не читал с Astetisk-ом не работал, но судя по http://xgu.ru/wiki/AMI там можно обойтись или встроенным телнет клиентом в связке с expect, или написать что надо на python (благо, биндинги, судя по всему, есть). А запускать опять же банально через ЗапуститьПриложение().
Если есть конкретная задача, можем посмотреть варианты решения.
12. Мищенко Вадим (vslimv) 22.01.15 13:01
(10) servs, ROM-Asterisk-Native насколько я знаю виндовый, а для линукса есть только у мико(далеко не бесплатно+куча **рни в подарок)+ она работает через богопротивный AJAM.
13. Мищенко Вадим (vslimv) 22.01.15 13:06
(11) q_i,
встроенным телнет клиентом в связке с expect

Немного не понял))
ЗапуститьПриложение() не канает. Нужно слушать события по telnet'у, причем желательно асинхронное поступление событий в 1с.
Хотя может я просто Вас не понял)
14. Ярослав Володимирович (myr4ik07) 23.01.15 10:11
(1) kostyaomsk, сколько вам можно писать "ХВАТИТЬ ПИСАТЬ, ПОЧТИ В КАЖДОМ СООБЩЕНИИ СВОЕЙ БЕЗПОЛЕЗНЫЙ КОММЕНТАРИЙ?????!!!!!", вы по другому не умете зарабатывать $m? Взрослый мужик, а хитрун еще тот. Стыдно!
AlexanderKai; +1 Ответить 1
15. q_i 23.01.15 17:44
(14) myr4ik07, во-первых, беСполезный, а во-вторых, для выяснения отношений есть ЛС, форум, обращение к модераторам и т.п.
Это касается и (3)
Надеюсь на Ваше понимание.
16. q_i 23.01.15 17:46
(13) vslimv, это скорее я не понял. Т.е. нужно открыть сокет, слушать его, а полученные данные передавать в 1С? Так? А кто и что будет в этот сокет писать/читать с другой стороны (со стороны клиента)?
17. Роман Ложкин (webester) 25.01.15 13:55
(15)А че ему можно писать че попало, а мне нельзя?
А че это вы тут указываете, если:
для выяснения отношений есть ЛС, форум, обращение к модераторам и т.п.
я предлагаю вам воспользоваться вашим же советом.
18. Мищенко Вадим (vslimv) 26.01.15 07:47
(16) q_i, Все именно так.Со стороны сервера asterisk висит AMI(Asterisk Manager API). Будет отсылать тебе после авторизации, все события в текстовом виде. Более подробно о нем и на русском тут .
Со стороны клиента ВК и события из нее)
В общем задача ее принимать текст из 1С и отправлять в AMI и наоборот из AMI в 1С. Сама ничего уметь не должна, разве что отправлять в 1С ошибку при подключении к сокету, если таковая имеется.
19. q_i 16.02.15 20:02
Проблема с Alert-ами заключалась в том, что в в include/AddInDefBase.h в прототипе метода ожидается WCHAR_T* (строка 2-хбайтовых символов), а передаётся wchar_t* (строка 4-хбайтовых символов; L"OK" - это 4-хбайтовые символы):
virtual bool ADDIN_API Alert(const WCHAR_T* text)

Поэтому нужно поменять
if (succeed)
    imsgbox->Alert(L"OK");
else
    imsgbox->Alert(L"Cancel");

на
WCHAR_T *msg = NULL;
if (succeed)
    ::convToShortWchar(&msg, L"OK");
else
    ::convToShortWchar(&msg, L"Cancel");
imsgbox->Alert(msg);
delete[] msg;
...Показать Скрыть
minimajack; +1 Ответить
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа