Windows7のvc2010でredis3.0をコンパイルして使用します
プロジェクトでは、複数のマシンが頻繁に読み取り、書き込み、およびいくつかのパラメーターの同期を行います。元の計画は、効率にいくらかの影響を与えたMySQL一時テーブルを介して実装されたため、redisに変更されました。このプロジェクトでは、redis、web、およびmysqlはLinuxプラットフォームであり、クライアントはWindows7プラットフォームのC ++アプリケーションプロセスであり、LoRaおよびその他のハードウェアデバイスを操作します。
1.hiredisをコンパイルします
インターネット上の多くのブログ投稿の説明によると、C ++環境でredisにアクセスするにはhiredisライブラリが必要です。ダウンロードしたredis3.0のソースコードから、hiredisは、プロジェクトに統合されていることが判明した以下ののディレクトリ構造です。
redis3.0 :├─deps
├─msvs
│├─hiredis
│├─lua
│├......
│├─Samples
│├─setups
│└─tools
├─src
│└─Win32_Interop
├─tests
└─utils
その中には、msvcディレクトリにhiredis.vcxprojファイルがあり、srcディレクトリにWin32_Interop.vcxprojファイルがあります。これら2つは、C ++クライアントが呼び出す必要のあるライブラリファイルです。
これらの2つの.vcxprojプロジェクトはvc2012バージョンであり、ソースコードは、自動派生、可変長パラメーターテンプレート、定数メンバーの割り当てなど、いくつかのCxx11構文を使用することに注意してください。したがって、ソースコードにいくつかの小さな変更が必要です。
1.1Win32_Interop.vcxprojをコンパイルします
ソリューションに追加し、[プロパティ]-> [プラットフォームプロパティ]-> [一般]で[プラットフォームツールセット]をv120からv100に変更し、[構成タイプ]を[静的ライブラリ(.lib)]に変更します。
多数をコンパイルしてレポートします。コンパイルエラー。心配しないでください。これらのエラーには実際には共通点があります。vimの正規式を使用して置き換えてください。
(1)ベクトルの直接初期化と割り当ての小さな変更
Win32_CommandLine.cppには、次のコードがあります。
static RedisParamterMapper g_redisArgMap = {...};
解決策:
ローダークラスを作成し、そのコンストラクターで変数に値を割り当ててから、たとえばグローバルローダー変数を定義します。
class g_redisArgMap_loader {
public:
g_redisArgMap_loader()
{
// QFork flags
g_redisArgMap.insert(std::pair<string, ParamExtractor*>(cQFork, &fp2)); // qfork [QForkControlMemoryMap handle] [parent process id]
...
}
...
};
static g_redisArgMap_loader g_redisArgMap_loader_object = g_redisArgMap_loader();
(2)for(auto…)ステートメント
for (auto p : sentinelSubCommands) {...}
解决:
for (vector<string>::iterator p = sentinelSubCommands.begin(); p != sentinelSubCommands.end(); p++) {...}
(3)可変長パラメーターテンプレート(dllfunctor_stdcall)
これを解決するのは面倒ではありません。win32_variadicfunctor.hのdllfunctor_stdcallの定義をコメントアウトしてから、vimで正規式を記述し、次のようにコードを置き換えます。
原始代码:
auto f_WSACleanup = dllfunctor_stdcall<int>("ws2_32.dll", "WSACleanup");
替换后的代码:
int (WSAAPI * f_WSACleanup)( void ) = (int(\_\_stdcall * )())DLLMap::getInstance().getProcAddress("ws2\_32.dll", "WSACleanup");
vim正则式:
:%s/auto\s*\(\w\+\)\s* = dllfunctor_\w\+<\([^>,]\+\),*\s*\([^>]\+\)>/\2 (WSAAPI * \1)(\3) = (\2(__stdcall *)(\3))DLLMap::getInstance().getProcAddress/gc
その他の小さな問題は自分で解決できます。
コンパイルが成功し、Win32_Interop.libファイルが生成されます。
1.2编译hiredis.vcxproj
ソリューションに追加します。[プロパティ]-> [プラットフォームプロパティ]-> [一般]で、[プラットフォームツールセット]をv120からv100に変更し、[構成タイプ]を[静的ライブラリ(.lib)]に変更します。[
追加のインクルードディレクトリ]で";に" $(ProjectDir)... \ src \ Win32_Interop "を追加します。
コンパイルして、winapifamily.hファイルが見つからないことを報告します。
(1)ソースコードに小さな変更を加える
前述のように、redis3.0のhiredis.vcxprojはvc2012以降のwindows 8.xをサポートし、winapifamily.hはWDK 8(Windowsドライバーキット)のヘッダーファイルです。ここでは、ソースコードにいくつかの小さな変更を加える必要があります。
ファイル「redis-3.0 \ src \ win32_interop \ ws2tcpip.h」に、次のコードを追加します。
#define PICEA_12345_INCLUDED 1
#if (PICEA_12345_INCLUDED)
#ifndef _Outptr_ // SAL2.0中的宏,vc2010的SAL1.0中未定义
#define _Outptr_
#endif
#ifndef _In_reads_bytes_ // SAL2.0中的宏,vc2010的SAL1.0中未定义,写个假的
#define _In_reads_bytes_(a)
#endif
#ifndef _Out_writes_opt_ // SAL2.0中的宏,vc2010的SAL1.0中未定义,写个假的
#define _Out_writes_opt_(a)
#endif
#endif
#if (PICEA_12345_INCLUDED || WINVER <= _WIN32_WINNT_WS03)
#include "win32_winapifamily.h"
#else
#include <winapifamily.h>
#endif
(2)コンパイル
编译成功,生成hiredis.lib文件。
1.3 libjemalloc、lua、RedisBenchmarkなどをコンパイルします。
これらのライブラリはすべて.cファイルです。
「マクロ定義」エラーが発生した場合は、ファイルの先頭に#include <errno.h>を追加して解決してください。
変数宣言エラーが発生した場合は、vc2010コンパイラがc関数ステートメントで変数宣言を許可していないことが原因です。次に例を示します。
void f(void) {
if (...) { /*statement*/ ... }
int i; //这里vc2010会报告错误
i=0;
}
解决方法: 将变量声明在函数开头即可
特に、Cxx11 / VC2013でのみ利用可能なisnanやisinfなどの関数は、インターネット上で見つけてプロジェクトに追加できます(vc2010-porting.cppファイルを作成してプロジェクトに追加しました)。
1.4 RedisCli、RedisCheckAofなどをコンパイルします。
これらのプロジェクトはRedisServerに依存しておらず、コンパイルされているかどうかには影響しません。
処理方法は1.3と同じです。
1.5RedisServerをコンパイルする
ソースコードへの変更は1.1および1.3と同じであり、isnanなどの関数を処理するためにvc2010-porting.cppが追加されています。
次に、コンパイルして渡します。
F5キーを押してデバッグすると、redis起動ウィンドウが表示されます
2.hiredisを使用する
新しいwin32プロジェクトを作成し、プロジェクト名、プロパティ->構成プロパティ-> VC ++ディレクトリ->インクルードディレクトリを右クリックし、hiredisのパスを
$(SolutionDir)redis-3.0 \ deps \ hiredisに追加します。
プロジェクト名->プロパティ->構成プロパティ-> VC ++ディレクトリ->ライブラリディレクトリを右クリックし、hiredis.libおよびWin32_Interop.lib (Solution D ir)(SolutionDir)のパスを追加します。
(S o l u t i o n D i r )(構成)\
プロジェクト名を右クリック->プロパティ->リンカー->入力->追加の依存関係、hiredis.lib、Win32_Interop、ws2_32.libを追加します
サンプルコード(テストに合格)
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <hiredis.h>
extern "C"
{
//#include <win32fixes.h>
}
#include <ICRSINT.H>
#include <windows.h>
#define REDIS_SERVER_IP "192.168.x.x"
#define REDIS_SERVER_PORT 6379
#define REDIS_SERVER_PASS "xxxxxx"
#pragma comment(lib, "ws2_32.lib")
using namespace std;
void redis_test_proc()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 1), &wsaData);
redisContext * redis_ctx_;
redisReply *reply;
struct timeval timeout = { 1, 500000 }; // 1.5 seconds
redis_ctx_ = redisConnectWithTimeout((char*)REDIS_SERVER_IP, REDIS_SERVER_PORT, timeout);
if (NULL != redis_ctx_ && redis_ctx_->err) {
printf("Connection error: %s\n", redis_ctx_->errstr);
exit(1);
}
reply = (redisReply *)redisCommand(redis_ctx_, "auth "REDIS_SERVER_PASS);
if (REDIS_REPLY_ERROR == reply->type) {
printf("Authentication failed: %s\n", reply->str);
}
freeReplyObject(reply);
/* Set a key */
reply = (redisReply *)redisCommand(redis_ctx_, "SET %s %s", "foo", "kivifriut is delicious ...");
if (REDIS_REPLY_ERROR == reply->type) {
printf("SET failed (%s:%d): %s\n", __FUNCTION__, __LINE__, reply->str);
// TODO: 延迟x秒重连
} else {
printf("SET foo: %s\n", reply->str);
}
freeReplyObject(reply);
/* Try a GET and two INCR */
reply = (redisReply *)redisCommand(redis_ctx_, "GET foo");
printf("GET foo: %s\n", reply->str);
freeReplyObject(reply);
redisFree(redis_ctx_);
}
int main(int argc, _TCHAR* argv[])
{
redis_test_proc();
system("pause");
return 0;
}
出力:
SET foo: OK
GET foo: kivifriut is delicious ...
请按任意键继续. . .
ソースコード:https:
//download.csdn.net/download/hylaking/10729376