Решил посмотреть, как работает внешняя компонента для 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НаСервере();
КонецПроцедуры
И она таки вертится: