Продолжаем эксперименты по скрещиванию харбора со всем, что движется.
Как известно, в платформе 1С есть т.н. "Технология внешних компонент", как это выглядит, можно посмотреть
здесь или
здесь.
Попробуем это дело переложить на Харбор.
За основу берем пример, описанный на habrahabr.ru, и засовываем код на С++ в .prg, обрамляя традиционным #pragma BEGINDUMP ... ENDDUMP
Точка входа в DLL будет выглядеть так:
BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
HB_SYMBOL_UNUSED( hModule );
HB_SYMBOL_UNUSED( ul_reason_for_call );
HB_SYMBOL_UNUSED( lpReserved );
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hb_vmInit( 0 ); /* Don't execute first linked symbol */
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
hb_vmQuit();
break;
}
return TRUE;
}
Метод "Test" реализуем на Харборе:
Function StrMerge(cString1, cString2)
Local cOutStr
cOutStr := cString1+cString2
Return cOutStr
Вызов этой функции из С-шного кода, по рекомендациям гуру, делаем так:
(добавить код в функцию CallAsFunc)
case eMethTest:
if (!lSizeArray || !paParams)
return false;
//TV_VT(pvarRetValue) = VTYPE_UI1;
//TV_UI1(pvarRetValue) = (paParams+1) -> strLen;
s1 = (paParams) -> pwstrVal;
s2 = (paParams+1) -> pwstrVal;
wc_s1 = (wchar_t*) s1.c_str();
wc_s2 = (wchar_t*) s2.c_str();
c_s1 = hb_wctomb(wc_s1);
c_s2 = hb_wctomb(wc_s2);
PHB_ITEM pItem1 = hb_itemPutC( NULL, c_s1 );
PHB_ITEM pItem2 = hb_itemPutC( NULL, c_s2 );
char * HbFuncName = "STRMERGE";
pResult = hb_itemDoC( HbFuncName, 2, (PHB_ITEM) pItem1 , (PHB_ITEM) pItem2 , 0 );
sResult = hb_itemGetC( pResult );
wsResult = hb_mbtowc((const char *) sResult) ;
hb_itemRelease( pItem2 );
hb_itemRelease( pItem1 );
wstring_to_p(std::wstring(wsResult), pvarRetValue);
ret = true;
break;
Для сборки DLL понадобится немного поплясать с бубном, особенно если использовать Borland C.
Компилятору bcc32 надо будет указать ключ -WU, чтобы тот включил режим Unicode, а для сборки через hbmk2 делаем так:
hbmk2.exe -cflag+=-CP1251 -gui -trace -hbdynvm -cpp -manifest=AddInNative.dll.embed.manifest AddInNative.prg AddInNative.def -LC:\MiniGUI\lib -lminigui >build.log
Без ключа -CP1251 русские имена методов, которые должна увидеть 1С, превращаются в кракозябры.
А MiniGui (можно и hwgui) нужна затем, чтобы при инициализации компоненты 1С не вываливала пустое консольное окно.
Код на языке 1С для проверки - вот такой:
Процедура ПриНачалеРаботыСистемы()
Попытка
Успех = ПодключитьВнешнююКомпоненту("E:\AddInNative.dll", "DemoVK", ТипВнешнейКомпоненты.Native);
Исключение
Сообщить("Не удалось загрузить внешнюю компоненту" + ИнформацияОбОшибке().Описание , СтатусСообщения.Важное);
Конецпопытки;
ДемоКомп = Новый("AddIn.DemoVK.AddInHarbour");
Попытка
ПриветМир = ДемоКомп.Тест("Привет, ", "Мир!");
Исключение
Сообщить("Ошибка выполнения внешней компоненты" + ИнформацияОбОшибке().Описание , СтатусСообщения.Важное);
Конецпопытки;
Сообщить(ПриветМир);
КонецПроцедуры
Полностью то, что получилось, можно взять отсюда:
пример со всеми нужными файлами тестовая конфигурация 1С -