刚开始在windows下使用c++访问reids各种报错,经过网上到处搜方案,终于可以在windows下访问redis了,
特将注意事项记录下来:
1.获取redis Window下的开发库源码,从github获取
windows版:https://github.com/MSOpenTech/redis/tree/2.6
2.解压下载的压缩包,进入msvs目录下,用vs2013打开RedisServer.sln解决方案
3.编译hiredis项目,生成hiredis.lib静态库
4.在自己的工程中使用c++ 访问hiredis
(1)设置项目属性 c/c++ -》代码生成-》运行库-》多线程调试 MTD
注:因为编译的hiredis属第三方静态库,必须跟本项目的运行库一致才不报错
(2)将库源码(github上面下载的)中deps\hiredis路径下的头文件,主要是hireids.h包含到自己的路径中
(3)将hiredis.lib, ws2_32.lib两个静态库添加到项目的依赖项中
(4)此时编译会提示类似于_strerror等未定义的错误,需要将redis-2.6\src目录下的win32fixes.h 和win32fixes.c拷贝到自己的工程目录下,并添加到工程文件中参与编译和链接
(5)此时还不够,需要定义几个宏,项目设置-》C/C++ -》预处理器,添加一下宏定义
WIN32 _DEBUG _LIB _WIN32 _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE _CRT_SECURE_NO_DEPRECATE
(6)此时编译还会报错:error C4996, 继续项目设置:连接器 -》 命令行 中添加 /NODEFAULTLIB:libcmt.lib
(7)包含头文件 时需要注意, 应该按照如下方式包含:
#include "hiredis.h"
#define NO_QFORKIMPL //这一行必须加才能正常使用
#include "win32fixes.h"
(8) main函数中初始化网络环境
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 1), &wsaData);
(9)现在可以开始写自己的项目代码并访问redis了
注:链接库的加载、可以在项目依赖项中设置,也可以代码中编写
编译的报错,也可以在连接器中添加/NODEFAULTLIB:libcmt.lib,也可以在代码中编写
本人都是在代码中编写
以下是demo代码,vs2010下编译
头文件RedisHandle.h
#ifndef _RedisHandle_H_
#define _RedisHandle_H_
#include <stdio.h>
#include "hiredis.h"
#include <string>
#define strcasecmp _stricmp
using namespace std;
#pragma comment(linker,"/NODEFAULTLIB:LIBCMT.lib")
#pragma comment (lib,"hiredis.lib")
/*添加socket链接库*/
#pragma comment(lib,"Ws2_32.lib")
//函数声明
redisContext* connectRedis();
void testConnectRedis();
boolean setExpire(string key,int expire);
boolean setExpire(string key,int expire,redisContext* context);
boolean setCacheValue(string key,string value);
boolean setCacheValue(string key,string value,int expire);
string getCacheValue(string key);
int getCacheValueLength(string key);
#endif //_RedisHandle_H_
源文件RedisHandle.cpp
/*
利用微软开发的redis的接口文件hiredis操作redis
源码生成hiredis.lib引用到项目,并且必须把win32fixes.c放到源文件(即main.cpp文件中),win32fixes.c依赖win32fixes.h,
注:
1、因为hiredis.lib中引用到win32fixes.h,但是貌似没有把win32fixes.c编译到lib中,故必须在源代码中引入
2、编译的hiredis.lib的项目代码生成-》运行库-》必须跟需要用到该静态库的项目一致,debug或release方式也必须一致,否则报错
*/
#include "RedisHandle.h"
redisContext* connectRedis()
{
//redis默认监听端口为6379 可以再配置文件中修改
redisContext* c = redisConnect("127.0.0.1", 6379);
if ( c->err)
{
redisFree(c);
printf("Connect to redisServer faile\n");
//强制退出
MessageBox(NULL, TEXT("redis连接失败,服务端即将退出,请先启动redis!"), TEXT("提示"), MB_ICONWARNING);
exit(0);
return NULL;
}
printf("Connect to redisServer Success\n");
return c;
}
//测试连接redis
void testConnectRedis()
{
connectRedis();
}
//设置key的生命周期
boolean setExpire(string key,int expire)
{
return setExpire(key,expire,nullptr);
}
//设置key的生命周期
boolean setExpire(string key,int expire,redisContext* context)
{
redisContext* c = context;
if(c==nullptr)
{
c=connectRedis();
}
if(c==NULL)
{
return false;
}
char buf[10]="";
itoa(expire,buf,10);
string command="expire "+key+" "+buf;
redisReply* r = (redisReply*)redisCommand(c, command.c_str());
if(r->type=REDIS_REPLY_INTEGER&&r->integer==1)
{
return true;
}
return false;
}
//设置key的值
boolean setCacheValue(string key,string value)
{
return setCacheValue(key,value,NULL);
}
//设置key的值以及生命周期
boolean setCacheValue(string key,string value,int expire)
{
redisContext* c = connectRedis();
if(c==NULL)
{
return false;
}
//const char* command1 = "set stest1 value1";
string command="set "+key+" "+value;
redisReply* r = (redisReply*)redisCommand(c, command.c_str());
if( NULL == r)
{
printf("Execut command1 failure\n");
redisFree(c);
return false;
}
if( !(r->type == REDIS_REPLY_STATUS && strcasecmp(r->str,"OK")==0))
{
printf("Failed to execute command[%s]\n",command.c_str());
freeReplyObject(r);
redisFree(c);
return false;
}
//设置生命周期
if(expire!=NULL)
{
if(!setExpire(key,expire,c))
{
freeReplyObject(r);
redisFree(c);
return false;
}
}
freeReplyObject(r);
redisFree(c);
printf("Succeed to execute command[%s]\n", command.c_str());
return true;
}
//获取key的值
string getCacheValue(string key)
{
redisContext* c = connectRedis();
if(c==NULL)
{
return "";
}
string command="get "+key;
//const char* command3 = "get stest1";
redisReply* r = (redisReply*)redisCommand(c, command.c_str());
//判断是否没查询到
if ( r->type == REDIS_REPLY_NIL)
{
printf("Failed to execute command[%s]\n",command.c_str());
freeReplyObject(r);
redisFree(c);
return "";
}
//判断返回的是否是字符串类型
if ( r->type != REDIS_REPLY_STRING)
{
printf("Failed to execute command[%s]\n",command.c_str());
freeReplyObject(r);
redisFree(c);
return "";
}
printf("The value of 'stest1' is %s\n", r->str);
string value =r->str;
freeReplyObject(r);
redisFree(c);
printf("Succeed to execute command[%s]\n", command.c_str());
return value;
}
//获取key的值的长度
int getCacheValueLength(string key)
{
redisContext* c = connectRedis();
if(c==NULL)
{
return -1;
}
string command = "strlen "+key;
//const char* command2 = "strlen stest1";
redisReply* r = (redisReply*)redisCommand(c, command.c_str());
//判断返回的是否是整型
if ( r->type != REDIS_REPLY_INTEGER)
{
printf("Failed to execute command[%s]\n",command.c_str());
freeReplyObject(r);
redisFree(c);
return -1;
}
int length = r->integer;
freeReplyObject(r);
redisFree(c);
printf("The length of 'stest1' is %d.\n", length);
printf("Succeed to execute command[%s]\n", command.c_str());
return length;
}
//以秒为单位返回key的剩余时间
int getCacheValueTLL(string key)
{
redisContext* c = connectRedis();
if(c==NULL)
{
return -1;
}
string command = "ttl "+key;
redisReply* r = (redisReply*)redisCommand(c, command.c_str());
//判断返回的是否是整型
if ( r->type != REDIS_REPLY_INTEGER)
{
printf("Failed to execute command[%s]\n",command.c_str());
freeReplyObject(r);
redisFree(c);
return -1;
}
int ttl = r->integer;
freeReplyObject(r);
redisFree(c);
printf("The ttl of 'stest1' is %d.\n", ttl);
printf("Succeed to execute command[%s]\n", command.c_str());
return ttl;
}
//int main()
//{
// WSADATA wsaData;
// WSAStartup(MAKEWORD(2,1), &wsaData);
// setCacheValue("a","b",100);
// getCacheValue("a");
// getCacheValueLength("b");
// getCacheValueTLL("a");
// getchar();
// return 0;
//}