1. 程式人生 > >libevent在windows下使用步驟詳解

libevent在windows下使用步驟詳解

libevent是一個常用的網路庫,下面就看看在windows下面編譯測試的過程吧。

一 環境

系統:win8.1
編譯器:VS2013
官方下載地址:http://libevent.org/
版本:2.0.22-stable

二 編譯靜態庫

1 解壓
把上面下載到libevent-2.0.22-stable.tar.gz解壓,得到libevent-2.0.22-stable資料夾


2 新增巨集定義
在libevent-2.0.22-stable資料夾下找到下面三個檔案:
event_iocp.c
evthread_win32.c
listener.c
開啟並在開頭加上巨集定義:
#define _WIN32_WINNT 0x0500

因為event_iocp.c裡用到<winbase.h>標頭檔案裡的函式定義,如InitializeCriticalSectionAndSpinCount,
<windows.h>會包含<winbase.h>,而<winbase.h>這個標頭檔案裡這個函式是這樣定義的:
#if (_WIN32_WINNT >= 0x0403)
 WINBASEAPI
 BOOL WINAPI
 InitializeCriticalSectionAndSpinCount(
     __out LPCRITICAL_SECTION lpCriticalSection,
     __in  DWORD dwSpinCount
     );

 WINBASEAPI
 DWORD
 WINAPI
 SetCriticalSectionSpinCount(
     __inout LPCRITICAL_SECTION lpCriticalSection,
     __in    DWORD dwSpinCount
     );
 #endif

所以要定義_WIN32_WINNT這個巨集,而且值要大於0x0403。
如果沒有這個巨集或不滿足條件,編譯器會假定這個函式沒有定義,
等到連結時再尋找它,這樣這個函式的符號就假定返回一個int,
而顯示標準庫檔案裡這個函式不是返回int,所以在連結時就會找不到這個函式符號。


注意:巨集一定要定義在#include <windows.h>之前,不然還是沒有作用。


3 編譯
使用vs的命令列工具,cd到libevent-2.0.22-stable目錄,執行指令碼makefile.nmake,命令如下:
nmake /f Makefile.nmake
這樣就會生成三個靜態庫:
libevent_core.lib
libevent_extras.lib
libevent.lib

三 使用示例

1 新建專案

新建一個控制檯“空”專案

2 拷貝檔案

2.1 在專案目錄下建一個libevent資料夾
2.2 在libevent中新建一個lib資料夾,將上面三個lib檔案copy到該目錄下。
2.3 在libevent中再新建一個include資料夾,
將libevent-2.0.22-stable\include下的檔案和資料夾copy到該目錄下,
將libevent-2.0.22-stable\WIN32-Code下的檔案和資料夾copy到該目錄下,
2個event2目錄下的檔案合併一起。

3 專案配置

VC++目錄:
包含目錄,新增剛剛新建的include目錄
庫目錄,新增剛剛的lib目錄;


C/C++:
程式碼生成-->執行庫:
Debug模式下選:多執行緒除錯 (/MTd),
Release下模式下選:多執行緒 (/MT)


聯結器:
輸入->附加依賴項:
ws2_32.lib
wsock32.lib
libevent.lib
libevent_core.lib
libevent_extras.lib
另外兩個庫ws2_32.lib和wsock32.lib是用來編譯Windows網路相關的程式庫。

4 測試程式碼

4.1 新建一個main.c檔案
4.2 從libevent-2.0.22-stable\sample目錄下拷貝time-test.c檔案中的程式碼到main中,程式碼如下:
#include <sys/types.h>


#include <event2/event-config.h>


#include <sys/stat.h>
#ifndef WIN32
#include <sys/queue.h>
#include <unistd.h>
#endif
#include <time.h>
#ifdef _EVENT_HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>


#include <event2/event.h>
#include <event2/event_struct.h>
#include <event2/util.h>


#ifdef WIN32
#include <winsock2.h>
#endif




struct timeval lasttime;


int event_is_persistent;


static void timeout_cb(evutil_socket_t fd, short event, void *arg)
{
	struct timeval newtime, difference;
	struct event *timeout = arg;
	double elapsed;


	evutil_gettimeofday(&newtime, NULL);
	evutil_timersub(&newtime, &lasttime, &difference);
	elapsed = difference.tv_sec +
		(difference.tv_usec / 1.0e6);


	printf("timeout_cb called at %d: %.3f seconds elapsed.\n",
		(int)newtime.tv_sec, elapsed);
	lasttime = newtime;


	if (!event_is_persistent) {
		struct timeval tv;
		evutil_timerclear(&tv);
		tv.tv_sec = 2;
		event_add(timeout, &tv);
	}
}


int main(int argc, char **argv)
{
	struct event timeout;
	struct timeval tv;
	struct event_base *base;
	int flags;


#ifdef WIN32
	WORD wVersionRequested;
	WSADATA wsaData;


	wVersionRequested = MAKEWORD(2, 2);


	(void)WSAStartup(wVersionRequested, &wsaData);
#endif


	if (argc == 2 && !strcmp(argv[1], "-p")) {
		event_is_persistent = 1;
		flags = EV_PERSIST;
	}
	else {
		event_is_persistent = 0;
		flags = 0;
	}


	/* Initalize the event library */
	base = event_base_new();


	/* Initalize one event */
	event_assign(&timeout, base, -1, flags, timeout_cb, (void*)&timeout);


	evutil_timerclear(&tv);
	tv.tv_sec = 2;
	event_add(&timeout, &tv);


	evutil_gettimeofday(&lasttime, NULL);


	event_base_dispatch(base);


	return (0);
}

4.3 編譯執行結果如圖: