開放、平等、協作、快速、分享
代碼git地址:https://github.com/criticalstack/libevhtp
1.Visual Studio 必須 筆者用的是VS2019
2.Libevent2庫 必須 git地址:https://github.com/libevent/libevent,libevent的windows版本編譯相對簡單)
3.CMake 必須 網上可下載,如果網上地址太慢。到 這里 下載
4.OpenSSL 可選 網上下載,也可以通過源代碼編譯
5.pthreads 可選 VS的插件管理里面安裝
6.onig(regex 可選 git地址:https://github.com/kkos/oniguruma
說明:圖中需要編譯的庫都會在源代碼里面提供,必須具備 1 和 3
按照原作者說明,采用cmake + “MSYS Makefiles“ 來進行編譯,這種方式我嘗試過,沒有成功。最終采用”Visual Studio“的方式來編譯。
1.打開代碼根目錄(包含CMakeLists.txt文件),創(chuàng)建build目錄
2.通過DOS(或者其他SHELL工具)進入到代碼目錄,進入build目錄
3.執(zhí)行命令 cmake -DLIBEVENT_INCLUDE_DIR=..packageincludelibevent-2.1.11 -DONIGURUMA_INCLUDE_DIR=..packageincludeoniguruma-6.9.3 ..
4.看到提示顯示創(chuàng)建失敗,提示缺少 LIBEVENT_THREAD,這是因為libevent庫編譯windows版本時沒有提供出這個庫,具體原因未知..
5.轉到根目錄下的cmake文件夾下,打開options.cmake文件,將”option (EVHTP_DISABLE_EVTHR "Disable evthread support" OFF)“ 這行的 OFF 改為 ON
6.繼續(xù)執(zhí)行步驟3代碼,會提示一些錯誤,大概意思就時文件已經被包含過,不過不影響,現在我們查看build目錄下,發(fā)現已經有了VS的項目文件libevhtp.sln
7.雙擊打開libevhtp.sln,選擇evhtp這個工程進行編譯,會提示如下信息:”無法解析的外部符號 __imp_bind,該符號在函數 evhtp_bind_sockaddr 中被引用“等信息,這是由于未配置windows下的WS2_32.Lib庫,添加再配置項里添加這個依賴
8.重新編譯發(fā)現生成發(fā)現沒有報錯,成功生成了evhtp.dll。但這里我發(fā)現另外個問題,沒有對應的lib生成。
9.查看對應的接口定義,是由EVHTP_EXPORT這個宏導出,這個宏定義在build目錄下的include下的config.h的文件中。在windows下,這個宏定義為空。
#ifndef EVHTP_NEED_EXPORT #if (defined __GNUC__ && __GNUC__ >= 4) || defined __INTEL_COMPILER || defined __clang__ # define EVHTP_EXPORT __attribute__ ((visibility("default"))) # else # define EVHTP_EXPORT __declspec(dllimport) # endif #else # if (defined __GNUC__ && __GNUC__ >= 4) || defined __INTEL_COMPILER || defined __clang__ # define EVHTP_EXPORT # else # define EVHTP_EXPORT __declspec(dllexport) # endif #endif
修改后的config.h開頭定義如下,重新定義一個是否導出的宏 EVHTP_NEED_EXPORT,將這宏放到預處理定義里,并刪除原來的 EVHTP_EXPORT宏。重新編譯后,包含evhtp.lib及evhtp.dll文件
新建一個工程,利用evhtp庫創(chuàng)建一個http服務器,看是否成功。代碼如下:
1 // main.cpp: 主程序入口 2 // 3 #include4 #include "evhtp.h" 5 #include6 7 evhtp_t* g_htp; 8 9 #define REGISTER_HTP_CB(path, cb, arg) evhtp_set_cb(g_htp, path, cb, arg) 10 11 void HtpCallBack(evhtp_request_t* req, void* a) 12 { 13 std::cout << "recv a command" << std::endl; 14 evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "application/json", 0, 0)); 15 evbuffer_add(req->buffer_out, "hello, evhtp! success.", sizeof("hello, evhtp! success.")); 16 evhtp_send_reply(req, EVHTP_RES_OK); 17 } 18 19 int main(int argc, const char* argv[]) 20 { 21 WSADATA wsaData; 22 WSAStartup(MAKEWORD(1, 1), &wsaData); 23 24 evbase_t* evbase = event_base_new(); 25 g_htp = evhtp_new(evbase, NULL); 26 evhtp_use_threads_wexit(g_htp, NULL, NULL, 16, NULL); 27 28 REGISTER_HTP_CB("/api", HtpCallBack, nullptr); 29 30 evhtp_bind_socket(g_htp, "0.0.0.0", 8080, 1024); 31 32 event_base_loop(evbase, 0); 33 34 WSACleanup(); 35 36 return 0; 37 } |
編譯后,運行程序。提示 無法定位程序點輸入點 evhtp_use_threads_wexit 。查找該函數定義在evhtp.c文件中,不過該函數是否編譯由 EVHTP_DISABLE_EVTHR 宏來控制,在上面步驟5里面,我們將這個編譯選型設置為ON,所以導致頭文件中由接口定義,但是卻沒有實現。
修改build/include目錄下的config文件中將 #define EVHTP_DISABLE_EVTHR代碼注釋掉,注意可能存在多行。重新編譯我們的evhtp庫,會提示找不到pthread.h找不到,將VS中NuGet找到pthread的庫安裝即可。
如果提示timespec重定義錯誤,在預處理宏中加上 HAVE_STRUCT_TIMESPEC 定義
編譯成功運行工程,通過web頁面發(fā)送請求,成功。通過ProcessExplorer工具查看,程序也是有17個線程。遇到過沒編譯好,只有一個線程情況。
附上我編譯后的源代碼地址:https://github.com/kswangxing/evhtp_win
里面包含編譯后代碼。
編譯環(huán)境:VS2019 64位