Господа,
у меня серьезный и важный вопрос, над которым я бьюсь головой об клавиатуру уже больше недели.
Я даже готов обсудить вознаграждение тому, кто мне поможет.
Вопрос такой: надо меня научить правильно ставить галочки в настройках линкера под VS 2015, чтобы у меня библиотека libevent линковалась к проекту на c++ (и, возможно, правильно билдить эту библиотеку).
Предыстория вопроса:
я прочитал пару мотивирующитъх статей насчет библиотеки libevent
(напрмер, эту: https://habrahabr.ru/post/217437/ ).
Начал я с того, что сделал девелоперскую машину под Ubuntu 16 LTS,
куда поставл g++ и собрал библиотеку из исходников по иструкциям с гитхаба.
( https://github.com/libevent/libevent )
Потом я написал простую программу test.cpp, в которой попробовал инициализировать библиотеку:
После небольшого замешательства я нормально собрал эту программу командой
g++ -std=c++11 -o test.ex test.cpp -levent
и запустил её.
./test.ex
Всё работает. Это пркрасно.
Затем я переписал из примеров немного более сложный пример...
Но как только я начал писать сам — мне понадобилась отладка.
И родная для меня система в этом смысле — Windows.
Ну, вы понимаете... родственников не выбирают...
А под Windows все совсем не так гладко.
Во первых, нужно собрать библиотеку из исходников.
По инструкции я делаю это при помощи CMake:
"CMake (Windows)
Install CMake: http://www.cmake.org
$ md build && cd build
$ cmake -G "Visual Studio 10" .. # Or whatever generator you want to use
$ start libevent.sln"
Cmake при сборке ругается на отсутствие OpenSSL, и тут уже не помогают никакие танцы с бубнами:
чтобы использовать OpenSSL под виндой, надо определить три магические переменные окружения
а как эти переменные определять — не написано нигде.
К счастью, если закрыта дверь — можно проверить окно...
libevent позволяет собрать себя без поддержки OpenSSL, дописыванием ключика -DEVENT__DISABLE_OPENSSL=on,
то есть командой
cmake -DEVENT__DISABLE_OPENSSL=on -G "Visual Studio 14 2015"
Меня, правда, немного смущают некоторые предупреждения, которые написала мне эта команда,
её вывод видно здесь:
Pic0
Но *.sln файл создаётся, и после запуска компиляции я получил набор *.lib — файлов в директории Debug:
event.lib, event_core.lib, event_extra.lib.
Pic1
А вот потом начались проблемы.
Никакие пляски с бубном не позволяют мне прилинковать эти библиотеки к C++ проекту.
Для полноты картины:
в моей системе путь к этим *.lib файлам — это C:\Programs\includes\libevent\lib\Debug
я засобывал их сюда:
Pic2
и сюда:
Pic3
и сюда:
Pic4
и даже сюда:
Pic5
При последней попытке создалась иллюзия того, что что то получилось. то есть проект нормально собрался. Но при запуске я мгновенно получил ошибку:
Pic6
Потом я сделал еще две жалкие попытки разобраться:
слинковать (потому что сборка obj-файла проходит без ошибок, заметьте) под виндой из командной строки (результат — тот же, не видит библиотеки)
Pic7
и попробовать сравнить содержимой obj — файлов, воспользовавшись под линуксом утилитой nm, а под виндой — dumpbin с опцией /symbols
Но разница слишком велика, я просто вижу в виндовом оьбъектном файле, что символ _event_init — UNDEFined.
Pic8
В общем, я не достиг успеха.
Помогите, пожалуйста, например — подсказав, как определить магические переменные для OpenSSL (может, библиотека толькоприкинулась, что она нормально собрана?),
или попробовав у себя собрать этот проект с этой библиотекой — возможно, у вас получится.
Здравствуйте, SteeLHeaD, Вы писали:
SLH>у меня серьезный и важный вопрос, над которым я бьюсь головой об клавиатуру уже больше недели.
А сами библиотеки линкуете?
Третий Рим должен пасть!
Re[2]: libevent: как её прилинковать к проекту под Windows?
Здравствуйте, GhostCoders, Вы писали:
GC>Здравствуйте, SteeLHeaD, Вы писали:
SLH>>у меня серьезный и важный вопрос, над которым я бьюсь головой об клавиатуру уже больше недели. GC>А сами библиотеки линкуете?
Я имею в виду Linker -> Input -> Additional Dependencies ?
Там список *.lib файлов, котрые линкуются, туда добавте event.lib, или как там они называются?
Третий Рим должен пасть!
Re: libevent: как её прилинковать к проекту под Windows?
Здравствуйте, GhostCoders, Вы писали:
GC>Там список *.lib файлов, котрые линкуются, туда добавте event.lib, или как там они называются?
Попробуйте все три линковать: event_core.lib, event_extra.lib, event.lib.
Еще, подозреваю там символа препроцессора нужно правильно устанавливать.
DLL файлов никаких не создалось после компиляции event? Поищите в той папке где вы event собирали, может какие-то DLL-ки завалялись?
Третий Рим должен пасть!
Re[2]: libevent: как её прилинковать к проекту под Windows?
R>что толку от library Directory если не указано какую либу линковать
А нельзя ли ка то поподробне показать, какие там кнопки нажимать, чтобы указать либу?
Re[4]: libevent: как её прилинковать к проекту под Windows?
Здравствуйте, GhostCoders, Вы писали: GC>DLL файлов никаких не создалось после компиляции event? Поищите в той папке где вы event собирали, может какие-то DLL-ки завалялись?
Нет, эта штука максимально кроссплатформенная и вообще DLL не создаёт.
Во всяком случае, как я понял из описаний.
И DLL — никакие не завалялись.
Re[3]: libevent: как её прилинковать к проекту под Windows?
GC>>Там список *.lib файлов, котрые линкуются, туда добавте event.lib, или как там они называются? GC>Попробуйте все три линковать: event_core.lib, event_extra.lib, event.lib.
Попробовал.
Ошибка при запуске — та же самая:
"---------------------------
LibeEx1.exe — System Error
---------------------------
The code execution cannot proceed because event.dll was not found. Reinstalling the program may fix this problem.
---------------------------
OK
---------------------------
"
Я думаю, дело здесь вот в чём: в этом месте, гдле указываются дополнительные зависимости,
можно вставлять только ДИНАМИЧЕСКИ подключаемые библиотеки.
Это — следствие того, что под виндой есть DLL-ки.
Но так как libevent не существует в виде DLL — значит, нужна какая то другая магия, чтобы линкер узнал о том, как слинковаться с этой библиотекой
Re[4]: libevent: как её прилинковать к проекту под Windows?
Спасибо,
я это делал и у меня это в исходном вопросе написано: http://junecat.ru/Storage/oth/le_pic5.jpg
Это не приводит к успеху, видимо, потому, что если засунуть библиотеку в это место —
то сборка происходит, но при запуске выдаётся ошибка
---------------------------
LibeEx1.exe — System Error
---------------------------
The code execution cannot proceed because event.dll was not found. Reinstalling the program may fix this problem.
---------------------------
OK
---------------------------
Думаю, что при это м линкер помечает ссылку в *.obj — файле как требующую динамического связывания
(то есть, как я понимаю, связывания при запуске программы) и в этом случае код из библиотеки даже не пытается вставиться в мой EXE шник
Re[4]: libevent: как её прилинковать к проекту под Windows?
GC>>Еще, подозреваю там символа препроцессора нужно правильно устанавливать. SLH>А что это такое и как этоделать?
Вкладка С\С++ -> Preprocessor -> Preprocessor Definitions
если DLL действительно нет (лучше поискать во всем подпапкам проекта) то символ будет в духе LIB_EVENT_USE_STATIC_LIB
А вообще лучше заголовочные файлы почитайте от libevent, event.h — там должно быть их использвание.
Третий Рим должен пасть!
Re[5]: libevent: как её прилинковать к проекту под Windows?
Здравствуйте, SteeLHeaD, Вы писали:
SLH>--------------------------- SLH>The code execution cannot proceed because event.dll was not found. Reinstalling the program may fix this problem. SLH>---------------------------
Проблема четко указана: не найдена event.dll
SLH>Я думаю, дело здесь вот в чём: в этом месте, гдле указываются дополнительные зависимости, SLH>можно вставлять только ДИНАМИЧЕСКИ подключаемые библиотеки.
Неправда. У вас просто либа собрана для динамической линковки, а .lib -- всего лишь переходник для загрузки .dll
SLH>Это — следствие того, что под виндой есть DLL-ки. SLH>Но так как libevent не существует в виде DLL — значит, нужна какая то другая магия, чтобы линкер узнал о том, как слинковаться с этой библиотекой
с .dll линковаться нельзя. обычно линкуются с .lib, и получают .exe который зависит от наличия .dll
Re[5]: libevent: как её прилинковать к проекту под Windows?
Спасибо за совет.
Да, такая штука, о которой Вы говорите — часто применяется в windows — программах.
Думаю, что здесь — не тот случай.
Потому что event.dll не существует в природе.
libevent — как я понял из описанийц — максимально кросплатформенна и не существует в виде DLL — ек.
Надо как то объяснить студии, что мне нужна в этом месте статическая линковка с либой event.lib.
И убрать эти либы из того места, в которое я их засунул в попытках хоть как то собрать проект
(junecat.ru/Storage/oth/le_pic5.jpg)
Re[7]: libevent: как её прилинковать к проекту под Windows?
Здравствуйте, SteeLHeaD, Вы писали:
SLH>Думаю, что здесь — не тот случай. SLH>Потому что event.dll не существует в природе. SLH>libevent — как я понял из описанийц — максимально кросплатформенна и не существует в виде DLL — ек.
Думаю, что существует.
Из файла \include\event2\visibility.h:
#if defined(event_shared_EXPORTS) || \
defined(event_extra_shared_EXPORTS) || \
defined(event_core_shared_EXPORTS) || \
defined(event_pthreads_shared_EXPORTS) || \
defined(event_openssl_shared_EXPORTS)
# if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
# define EVENT2_EXPORT_SYMBOL __global
# elif defined __GNUC__
# define EVENT2_EXPORT_SYMBOL __attribute__ ((visibility("default")))
# elif defined(_MSC_VER)
# define EVENT2_EXPORT_SYMBOL __declspec(dllexport)
# else
# define EVENT2_EXPORT_SYMBOL /* unknown compiler */# endif
#else/* event_*_EXPORTS */# define EVENT2_EXPORT_SYMBOL
#endif/* event_*_EXPORTS */
/** We need to dllimport event_debug_logging_mask_ into event_extra */#if defined(_MSC_VER)
# if defined(event_core_shared_EXPORTS) /** from core export */# define EVENT2_CORE_EXPORT_SYMBOL __declspec(dllexport)
# elif defined(event_extra_shared_EXPORTS) /** from extra import */# define EVENT2_CORE_EXPORT_SYMBOL __declspec(dllimport)
# endif
#endif/* _MSC_VER */#if !defined(EVENT2_CORE_EXPORT_SYMBOL)
# define EVENT2_CORE_EXPORT_SYMBOL EVENT2_EXPORT_SYMBOL
#endif
проверяется компилятор _MSC_VER — это сутидя Майкрософта.
И если компилятор Макйрософт — по используются специфицные для MS вещи такие как __declspec(dllexport) — помечает что данная функция будет экспортирована из ДЛЛ.
__declspec(dllimport) — наоборот — функция будет браться из DLL.
Вещи, стандартные для Windows. Так что подразумевается какая-то DLL.
Третий Рим должен пасть!
Re[6]: libevent: как её прилинковать к проекту под Windows?
Здравствуйте, GhostCoders, Вы писали: GC>Здравствуйте, SteeLHeaD, Вы писали:
GC>>>Еще, подозреваю там символа препроцессора нужно правильно устанавливать. SLH>>А что это такое и как этоделать? GC>Вкладка С\С++ -> Preprocessor -> Preprocessor Definitions GC>если DLL действительно нет (лучше поискать во всем подпапкам проекта) то символ будет в духе LIB_EVENT_USE_STATIC_LIB GC>А вообще лучше заголовочные файлы почитайте от libevent, event.h — там должно быть их использвание.
1) я попробобвал.
поставил эти Preprocessor Definitions как показано на картинке:
Ничего не изменилось — то есть я опять получал ошибку при запуске.
2)ТОгда я убрал эти три библиотеки из того места, где указываются Additional Dependencies для линкера...
(ну, потому что я вижу там файлы типа kernel32.dll, пот которым видно, что их можно линковать только динамически, и делаю вывод, что всё, что там указано — преждназначено для динамической линковки.) — и обратно получил обратно ошибку линкера "error LNK2019: unresolved external symbol _event_init referenced in function _main"
3) я посмотрел в файл event.h — он размером три килобайта, больше чем наполовину состоит из copyright — сообщения, и не сожержит никаких примеров использования или специальных слов типа "в случае использования под windows — сделайте вот это"
Можно посомтреть на этот файл на гитхабе: https://github.com/libevent/libevent
Re[7]: libevent: как её прилинковать к проекту под Windows?
Здравствуйте, SteeLHeaD, Вы писали:
SLH>3) я посмотрел в файл event.h — он размером три килобайта, больше чем наполовину состоит из copyright — сообщения, и не сожержит никаких примеров использования или специальных слов типа "в случае использования под windows — сделайте вот это"
Не нужно воспринимать это буквально, там еще куча всяких заголовков.
Вообщем, попробуйте определить символ препроцессора EVENT2_EXPORT_SYMBOL
Третий Рим должен пасть!
Re[8]: libevent: как её прилинковать к проекту под Windows?
Здравствуйте, GhostCoders, Вы писали:
GC>Здравствуйте, SteeLHeaD, Вы писали:
SLH>>Думаю, что здесь — не тот случай. SLH>>Потому что event.dll не существует в природе. SLH>>libevent — как я понял из описанийц — максимально кросплатформенна и не существует в виде DLL — ек. GC>Думаю, что существует.
GC>Из файла \include\event2\visibility.h: GC>
GC>проверяется компилятор _MSC_VER — это сутидя Майкрософта. GC>И если компилятор Макйрософт — по используются специфицные для MS вещи такие как __declspec(dllexport) — помечает что данная функция будет экспортирована из ДЛЛ. GC>__declspec(dllimport) — наоборот — функция будет браться из DLL. GC>Вещи, стандартные для Windows. Так что подразумевается какая-то DLL.
КРУТО!
теперь у меня программа запускается, сообщение при запуске:
[warn] evsig_init_: socketpair: Either the application has not called WSAStartup, or WSAStartup failed.
Дорогой человек, как я могу тебя отблагодарить?
ты не послал меня с первого же замечания,
и вы вместе добиваемся победы.
Re[9]: libevent: как её прилинковать к проекту под Windows?
SLH>КРУТО! SLH>теперь у меня программа запускается, сообщение при запуске: SLH>
SLH>[warn] evsig_init_: socketpair: Either the application has not called WSAStartup, or WSAStartup failed.
SLH>
SLH>Дорогой человек, как я могу тебя отблагодарить? SLH>ты не послал меня с первого же замечания, SLH>и вы вместе добиваемся победы.
Пишу вдогонку — но по прежнему не работает...
Сейчас программа под виндой выглядит как
программа
#include <memory>
#include <cstdint>
#include <iostream>
#include <evhttp.h>
using namespace std;
int main()
{
if (!event_init()) {
cout << "Failed to init libevent." << endl;
}
else {
cout << "Libevent initialised!" << endl;
char const SrvAddress[] = "192.168.10.53";
uint16_t SrvPort = 5555;
unique_ptr<evhttp, decltype(&evhttp_free)> Server(evhttp_start(SrvAddress, SrvPort), &evhttp_free);
if (!Server)
{
cout << "Failed to init http server." << std::endl;
return -1;
}
void(*OnReq)(evhttp_request *req, void *) = [](evhttp_request *req, void *)
{
auto *OutBuf = evhttp_request_get_output_buffer(req);
if (!OutBuf)
return;
evbuffer_add_printf(OutBuf, "<html><body><center><h1>Hello World! under Windows!</h1></center></body></html>");
evhttp_send_reply(req, HTTP_OK, "", OutBuf);
};
evhttp_set_gencb(Server.get(), OnReq, nullptr);
if (event_dispatch() == -1)
{
cout << "Failed to run messahe loop." << std::endl;
return -1;
}
}
return 0;
}
и выдаёт сообющение об ошибке
C:\MyProjects\Cpp\LibeEx1\Debug>LibeEx1.exe
[warn] evsig_init_: socketpair: Either the application has not called WSAStartup, or WSAStartup failed.
Libevent initialised!
[warn] socket: Either the application has not called WSAStartup, or WSAStartup failed.
Failed to init http server.