libevent: как её прилинковать к проекту под Windows?
От: SteeLHeaD  
Дата: 14.02.18 12:46
Оценка:
Господа,
у меня серьезный и важный вопрос, над которым я бьюсь головой об клавиатуру уже больше недели.
Я даже готов обсудить вознаграждение тому, кто мне поможет.
Вопрос такой: надо меня научить правильно ставить галочки в настройках линкера под VS 2015, чтобы у меня библиотека libevent линковалась к проекту на c++ (и, возможно, правильно билдить эту библиотеку).

Предыстория вопроса:
я прочитал пару мотивирующитъх статей насчет библиотеки libevent
(напрмер, эту: https://habrahabr.ru/post/217437/ ).
Начал я с того, что сделал девелоперскую машину под Ubuntu 16 LTS,
куда поставл g++ и собрал библиотеку из исходников по иструкциям с гитхаба.
( https://github.com/libevent/libevent )
Потом я написал простую программу test.cpp, в которой попробовал инициализировать библиотеку:

#include <memory>
#include <cstdint>
#include <iostream>
#include <evhttp.h>
#include <string>
#include <fstream>

using namespace std;

int main(){

cout<< "Hi!" << endl ;

if ( !event_init()) 
  cout << "Failed to init libevent." << endl;
else
  cout << "libevent init successfully!" << endl;


return 0;
}


После небольшого замешательства я нормально собрал эту программу командой
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 под виндой, надо определить три магические переменные окружения
OPENSSL_ROOT_DIR
OPENSSL_INCLUDE_DIR
OPENSSL_CRYPTO_LIBRARY

а как эти переменные определять — не написано нигде.
К счастью, если закрыта дверь — можно проверить окно...
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 (может, библиотека толькоприкинулась, что она нормально собрана?),
или попробовав у себя собрать этот проект с этой библиотекой — возможно, у вас получится.

Заранее спасибо за советы.
libevent c++ visual studio linker openssl
Re: libevent: как её прилинковать к проекту под Windows?
От: GhostCoders Россия  
Дата: 14.02.18 12:53
Оценка:
Здравствуйте, SteeLHeaD, Вы писали:

SLH>у меня серьезный и важный вопрос, над которым я бьюсь головой об клавиатуру уже больше недели.

А сами библиотеки линкуете?
Третий Рим должен пасть!
Re[2]: libevent: как её прилинковать к проекту под Windows?
От: GhostCoders Россия  
Дата: 14.02.18 12:56
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Здравствуйте, SteeLHeaD, Вы писали:


SLH>>у меня серьезный и важный вопрос, над которым я бьюсь головой об клавиатуру уже больше недели.

GC>А сами библиотеки линкуете?
Я имею в виду Linker -> Input -> Additional Dependencies ?
Там список *.lib файлов, котрые линкуются, туда добавте event.lib, или как там они называются?
Третий Рим должен пасть!
Re: libevent: как её прилинковать к проекту под Windows?
От: reversecode google
Дата: 14.02.18 12:57
Оценка: +1
что толку от library Directory если не указано какую либу линковать
Re[3]: libevent: как её прилинковать к проекту под Windows?
От: GhostCoders Россия  
Дата: 14.02.18 13:05
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Там список *.lib файлов, котрые линкуются, туда добавте event.lib, или как там они называются?

Попробуйте все три линковать: event_core.lib, event_extra.lib, event.lib.

Еще, подозреваю там символа препроцессора нужно правильно устанавливать.
DLL файлов никаких не создалось после компиляции event? Поищите в той папке где вы event собирали, может какие-то DLL-ки завалялись?
Третий Рим должен пасть!
Re[2]: libevent: как её прилинковать к проекту под Windows?
От: SteeLHeaD  
Дата: 14.02.18 13:09
Оценка:
Здравствуйте, reversecode, Вы писали:


R>что толку от library Directory если не указано какую либу линковать

А нельзя ли ка то поподробне показать, какие там кнопки нажимать, чтобы указать либу?
Re[4]: libevent: как её прилинковать к проекту под Windows?
От: SteeLHeaD  
Дата: 14.02.18 13:11
Оценка:
Здравствуйте, GhostCoders, Вы писали:
GC>DLL файлов никаких не создалось после компиляции event? Поищите в той папке где вы event собирали, может какие-то DLL-ки завалялись?
Нет, эта штука максимально кроссплатформенная и вообще DLL не создаёт.
Во всяком случае, как я понял из описаний.
И DLL — никакие не завалялись.
Re[3]: libevent: как её прилинковать к проекту под Windows?
От: reversecode google
Дата: 14.02.18 13:15
Оценка:
в ютубе полно видео, ну ок
давайте я поищу за вас
https://youtu.be/F4mB2Atu6J4?t=344
Re[4]: libevent: как её прилинковать к проекту под Windows?
От: SteeLHeaD  
Дата: 14.02.18 13:18
Оценка:
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?
От: SteeLHeaD  
Дата: 14.02.18 13:24
Оценка:
Здравствуйте, reversecode, Вы писали:


R>в ютубе полно видео, ну ок

R>давайте я поищу за вас
R>https://youtu.be/F4mB2Atu6J4?t=344

Спасибо,
я это делал и у меня это в исходном вопросе написано:
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?
От: SteeLHeaD  
Дата: 14.02.18 13:27
Оценка:
GC>Еще, подозреваю там символа препроцессора нужно правильно устанавливать.
А что это такое и как этоделать?
Re[5]: libevent: как её прилинковать к проекту под Windows?
От: GhostCoders Россия  
Дата: 14.02.18 13:32
Оценка:
Здравствуйте, SteeLHeaD, Вы писали:


GC>>Еще, подозреваю там символа препроцессора нужно правильно устанавливать.

SLH>А что это такое и как этоделать?
Вкладка С\С++ -> Preprocessor -> Preprocessor Definitions
если DLL действительно нет (лучше поискать во всем подпапкам проекта) то символ будет в духе LIB_EVENT_USE_STATIC_LIB
А вообще лучше заголовочные файлы почитайте от libevent, event.h — там должно быть их использвание.
Третий Рим должен пасть!
Re[5]: libevent: как её прилинковать к проекту под Windows?
От: K13 http://akvis.com
Дата: 14.02.18 13:35
Оценка:
Здравствуйте, 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?
От: reversecode google
Дата: 14.02.18 13:38
Оценка:
правильную lib укажите (скорее всего *core.lib)
Re[6]: libevent: как её прилинковать к проекту под Windows?
От: SteeLHeaD  
Дата: 14.02.18 13:41
Оценка:
K13>Проблема четко указана: не найдена event.dll

Спасибо за совет.
Да, такая штука, о которой Вы говорите — часто применяется в windows — программах.

Думаю, что здесь — не тот случай.
Потому что event.dll не существует в природе.
libevent — как я понял из описанийц — максимально кросплатформенна и не существует в виде DLL — ек.

Надо как то объяснить студии, что мне нужна в этом месте статическая линковка с либой event.lib.
И убрать эти либы из того места, в которое я их засунул в попытках хоть как то собрать проект
(junecat.ru/Storage/oth/le_pic5.jpg)
Re[7]: libevent: как её прилинковать к проекту под Windows?
От: GhostCoders Россия  
Дата: 14.02.18 13:46
Оценка:
Здравствуйте, 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?
От: SteeLHeaD  
Дата: 14.02.18 14:00
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Здравствуйте, SteeLHeaD, Вы писали:



GC>>>Еще, подозреваю там символа препроцессора нужно правильно устанавливать.

SLH>>А что это такое и как этоделать?
GC>Вкладка С\С++ -> Preprocessor -> Preprocessor Definitions
GC>если DLL действительно нет (лучше поискать во всем подпапкам проекта) то символ будет в духе LIB_EVENT_USE_STATIC_LIB
GC>А вообще лучше заголовочные файлы почитайте от libevent, event.h — там должно быть их использвание.

1) я попробобвал.
поставил эти Preprocessor Definitions как показано на картинке:
  http://junecat.ru/Storage/oth/le_pic9.jpg


Ничего не изменилось — то есть я опять получал ошибку при запуске.

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?
От: GhostCoders Россия  
Дата: 14.02.18 14:09
Оценка:
Здравствуйте, SteeLHeaD, Вы писали:

SLH>3) я посмотрел в файл event.h — он размером три килобайта, больше чем наполовину состоит из copyright — сообщения, и не сожержит никаких примеров использования или специальных слов типа "в случае использования под windows — сделайте вот это"

Не нужно воспринимать это буквально, там еще куча всяких заголовков.
Вообщем, попробуйте определить символ препроцессора EVENT2_EXPORT_SYMBOL
Третий Рим должен пасть!
Re[8]: libevent: как её прилинковать к проекту под Windows?
От: SteeLHeaD  
Дата: 14.02.18 14:14
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Здравствуйте, SteeLHeaD, Вы писали:


SLH>>Думаю, что здесь — не тот случай.

SLH>>Потому что event.dll не существует в природе.
SLH>>libevent — как я понял из описанийц — максимально кросплатформенна и не существует в виде DLL — ек.
GC>Думаю, что существует.

GC>Из файла \include\event2\visibility.h:

GC>
GC>#if defined(event_shared_EXPORTS) || \
GC>    defined(event_extra_shared_EXPORTS) || \
GC>    defined(event_core_shared_EXPORTS) || \
GC>    defined(event_pthreads_shared_EXPORTS) || \
GC>    defined(event_openssl_shared_EXPORTS)

GC># if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
GC>#  define EVENT2_EXPORT_SYMBOL __global
GC># elif defined __GNUC__
GC>#  define EVENT2_EXPORT_SYMBOL __attribute__ ((visibility("default")))
GC># elif defined(_MSC_VER)
GC>#  define EVENT2_EXPORT_SYMBOL __declspec(dllexport)
GC># else
GC>#  define EVENT2_EXPORT_SYMBOL /* unknown compiler */
GC># endif

GC>#else /* event_*_EXPORTS */

GC># define EVENT2_EXPORT_SYMBOL

GC>#endif /* event_*_EXPORTS */

GC>/** We need to dllimport event_debug_logging_mask_ into event_extra */
GC>#if defined(_MSC_VER)
GC># if defined(event_core_shared_EXPORTS) /** from core export */
GC>#  define EVENT2_CORE_EXPORT_SYMBOL __declspec(dllexport)
GC># elif defined(event_extra_shared_EXPORTS) /** from extra import */
GC>#  define EVENT2_CORE_EXPORT_SYMBOL __declspec(dllimport)
GC># endif
GC>#endif /* _MSC_VER */
GC>#if !defined(EVENT2_CORE_EXPORT_SYMBOL)
GC># define EVENT2_CORE_EXPORT_SYMBOL EVENT2_EXPORT_SYMBOL
GC>#endif
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?
От: SteeLHeaD  
Дата: 14.02.18 14:19
Оценка:
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.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.