MongoDb win32 下 C++驱动 浅析

最近需要在win32系统下用C++编译器测试MongoDb的性能,所以花了近一周的时间对MongoDb进行了初步的研究。

 

这里对于MongoDb的优势和一些规则就不细说了,详见

MongoDB实战中文版.pdf

MongoDB权威指南.pdf

 

在http://www.mongodb.org下载了最新版的,但是发现没有win32下的C++驱动,不得已,继续查找资料。

终于找到了一个1.2.1的windows32版本:

http://downloads.mongodb.org/win32/mongodb-win32-i386-1.2.1.zip

其中含有

执行该文件即可启动mongodb服务程序。

解压文件内还包含了c++的头文件和库文件。

将他们放到以下目录:

D:\mongodb\include

D:\mongodb\lib

所以打算利用它们来写mongodb客户程序。

 

但是

首先需要有boost,因为mongodb-win32-i386-1.2.1.zip里提供的mongodb库文件

D:\mongodb\1.2.1\mongodb-win32-i386-1.2.1\lib\mongoclient.lib

是用vs2008 + boost_1_35_0编译出来的,懒得重新编译mongodb,因此也对应的使用vs2008 + boost_1_35_0编译环境即可使用这个mongoclient.lib,boost_1_35_0从boost官网下载即可。

编译boost分两步:

1.执行D:\1.2.1\boost\boost_1_35_0\tools\jam\build_dist.bat

2.将第一步生成的bjam.exe拷贝到D:\boost\boost_1_35_0,然后执行:

cd D:\boost\boost_1_35_0

bjam.exe link=static threading=multivariant=release runtime-link=static --without-python --toolset=msvc-9.0

 

其中各参数的含义如下:

--build-dir=<builddir>  编译的临时文件会放在builddir里(编译完就可以把它删除了)

--stagedir=<stagedir> 存放编译后库文件的路径,默认是stage

--build-type=complete 编译所有版本,不然只会编译一小部分版本

(相当于variant=release,threading=multi;link=shared|static;runtime-link=shared)

variant=debug|release  决定编译什么版本(Debug orRelease)

link=static|shared  决定使用静态库还是动态库

threading=single|multi  决定使用单线程还是多线程库

runtime-link=static|shared 决定是静态还是动态链接C/C++标准库

--with-<library> 只编译指定的库,如输入--with-regex就只编译regex库了

--show-libraries 显示需要编译的库名称

 

完成后即会生成很多lib库,比如libboost_program_options-vc90-mt-s-1_35.lib,把这些lib库文件(搜索lib关键字)全部拷贝到D:\mongodb\uselib目录(uselib目录是我自己建立的)。

 

为了重复利用,以及方便以后可能delphi等其他编译器的运用,决定将一些常用功能编译成dll。

 

首先利用vs2008建立win32工程DLL,并做下设置:

1.工具-->选项-->项目和解决方案-->VC++目录

加上对应的包含文件:

D:\boost\boost_1_35_0

D:\mongodb\include\mongo

加上对应的库文件:

D:\mongodb\uselib

D:\mongodb\lib

(注:本来用的是1.2.1版本,但是我的系统中发生了点问题,后来用了1.8.1版本,但是驱动的头文件和库文件都没变)

2.项目-->属性(Alt+F7)-->配置属性-->C/C++-->代码生成-->运行时库选为多线程(/MT),即是静态的,不要用DLL。(对应boost库中”-mt-s-“名称)。

3. 项目-->属性(Alt+F7)-->配置管理器-->活动方案为release。(如果是debug会报错找不到-mt-sgd-)。

 

编译代码如下

 

// MongoDb.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"

#include <iostream>
#include "client/dbclient.h"
#pragma comment(lib, "mongoclient.lib")
#pragma comment(lib, "wsock32.lib")
using namespace std;
string errmsg;
string table = "hsds.logs";
mongo::DBClientConnection conn;
bool IfOpened = false;

void Ltrim(char *sStr)
{
	unsigned int i;
	if (strlen(sStr) <= 0) return;
	for (i = 0; i < strlen(sStr); i++)
		if (sStr[i] != ' ')
			break;
	strcpy(sStr, sStr + i);
	return;
}

void Rtrim(char *sStr)
{
	int i;
	if (strlen(sStr) <= 0) return;
	for (i = strlen(sStr) - 1; i >= 0; i--)
		if (sStr[i] != ' ')
			break;
	sStr[i + 1] = '\0';
	return;
}

void AllTrim(char *sStr)//去掉前后空格
{
	Ltrim(sStr);
	Rtrim(sStr);
}



extern "C" __declspec(dllexport) int MongoDbOpen(const char * ipport)
{
	if (!conn.connect(string(ipport), errmsg)) {
		cout << errmsg << endl;
        return -1;
    }
	IfOpened = true;
	return 1;
}

extern "C" __declspec(dllexport) int MongoDbInsert(char *format,...)//("name << %s << age << %d << email << %s << address << %s","wangjm",24,"419443006@qq.com","sadfsf");
{
	if(IfOpened)
	{
		va_list args;
		va_start(args,format);
		int pos = 0;
		char colname[1000];
		mongo::BSONObjBuilder query;
		char *tmp = format;
		while(*format != '\0' )
		{
			// string
			if( (*format == '%')&&(*(format+1) == 's') )//%s
			{
				char* s = va_arg( args, char * );
				query << colname << s;
				format = format + 2;
			}
			// MongoDb中用''存入单个字符,会转换成aci2
			// character
			else if( (*format == '%')&&(*(format+1) == 'c') )//%c
			{
				char c = (char)va_arg( args, int );//在可变长参数中,应用的是"加宽"原则。也就是char类型被扩展成int
				//printf("%c\n",c);
				char str[2];
				str[0] = c;
				str[1] = '\0';
				query << colname << str;
				format = format + 2;
			}
			// integer
			else if( (*format == '%')&&(*(format+1) == 'd') )//%d
			{
				int d = va_arg( args, int );
				query << colname << d;
				format = format + 2;
			}
			else if( (*format == '%')&&(*(format+1) == 'f') )//%f 
			{
				double f = va_arg( args, double);//在可变长参数中,应用的是"加宽"原则。也就是float类型被扩展成double,但是为了保证数据的准确性,当位数不满足float要求时,填充进随机数,这里直接用double型
				query << colname << f;
				format = format + 2;
			}
			/*
			else if( (*format == '%')&&(*(format+1) == 'l') )//%l 
			{
				long f = va_arg( args, long);
				query << colname << f;
				format = format + 2;
			}
			*/
			else if( (*format == '<') && (*(format+1) == '<'))
			{
				memset((void *)colname,'\0',sizeof colname);
				strncpy(colname,tmp,pos);
				AllTrim(colname);
				pos = 0;
				format = format + 2;
				tmp = format;
			}
			else
			{
				pos++;
				format++;
			}
		}
		va_end( args );
		conn.insert(table, query.obj());
	}
	return 0;
}


extern "C" __declspec(dllexport) int MongoDbSelect(char *format = "all",...)
{
	if(IfOpened)
	{
		va_list args;
		va_start(args,format);
		int pos = 0;
		char colname[1000];
		mongo::BSONObjBuilder query;
		char *tmp = format;
		if(strcmp(format,"all") != 0)
		{
			while(*format != '\0' )
			{
				// string
				if( (*format == '%')&&(*(format+1) == 's') )
				{
					char* s = va_arg( args, char * );
					query << colname << s;
					//query.append(colname,s);
					format = format + 2;
				}
				// MongoDb中用''存入单个字符,会转换成aci2
				// character
				else if( (*format == '%')&&(*(format+1) == 'c') )//%c
				{
					char c = (char)va_arg( args, int );//在可变长参数中,应用的是"加宽"原则。也就是char类型被扩展成int
					//printf("%c\n",c);
					char str[2];
					str[0] = c;
					str[1] = '\0';
					query << colname << str;
					format = format + 2;
				}
				// integer
				else if( (*format == '%')&&(*(format+1) == 'd') ) 
				{
					int d = va_arg( args, int );
					query << colname << d;
					//query.append(colname,d);
					format = format + 2;
				}
				else if( (*format == '%')&&(*(format+1) == 'f') ) 
				{
					double f = va_arg( args, double);//在可变长参数中,应用的是"加宽"原则。也就是float类型被扩展成double
					query << colname << f;
					//query.append(colname,f);
					format = format + 2;
				}
				else if( (*format == '<') && (*(format+1) == '<'))
				{
					memset((void *)colname,'\0',sizeof colname);
					//printf("%s\n",tmp);
					strncpy(colname,tmp,pos);
					AllTrim(colname);
					
					pos = 0;
					format = format + 2;
					tmp = format;
				}
				else
				{
					pos++;
					format++;
				}
			}
		}
		va_end( args );
		auto_ptr<mongo::DBClientCursor> cursor = conn.query(table, query.obj());//C++的auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理
		while (cursor->more()) 
		{
			mongo::BSONObj obj = cursor->next();
			cout << obj.jsonString() << endl;
		}
	}
    return 0;
}


extern "C" __declspec(dllexport) int MongoDbRemove(char *format = "all",...)
{
	if(IfOpened)
	{
		va_list args;
		va_start(args,format);
		int pos = 0;
		char colname[1000];
		mongo::BSONObjBuilder query;
		char *tmp = format;
		if(strcmp(format,"all") != 0)
		{
			while(*format != '\0' )
			{
				// string
				if( (*format == '%')&&(*(format+1) == 's') )
				{
					char* s = va_arg( args, char * );
					query << colname << s;
					//query.append(colname,s);
					format = format + 2;
				}
				// MongoDb中用''存入单个字符,会转换成aci2
				// character
				else if( (*format == '%')&&(*(format+1) == 'c') )//%c
				{
					char c = (char)va_arg( args, int );//在可变长参数中,应用的是"加宽"原则。也就是char类型被扩展成int
					//printf("%c\n",c);
					char str[2];
					str[0] = c;
					str[1] = '\0';
					query << colname << str;
					format = format + 2;
				}
				// integer
				else if( (*format == '%')&&(*(format+1) == 'd') ) 
				{
					int d = va_arg( args, int );
					query << colname << d;
					//query.append(colname,d);
					format = format + 2;
				}
				else if( (*format == '%')&&(*(format+1) == 'f') ) 
				{
					double f = va_arg( args, double);
					query << colname << f;
					//query.append(colname,f);
					format = format + 2;
				}
				else if( (*format == '<') && (*(format+1) == '<'))
				{
					memset((void *)colname,'\0',sizeof colname);
					//printf("%s\n",tmp);
					strncpy(colname,tmp,pos);
					AllTrim(colname);
					
					pos = 0;
					format = format + 2;
					tmp = format;
				}
				else
				{
					pos++;
					format++;
				}
			}
		}
		va_end( args );
		conn.remove(table, query.obj());
	}
	return 0;
}

(记得提取函数生成头文件,以后调用dll如果不想自己重新预定义函数时,需要用到头文件)

编程成功后会生成

MongoDb.exp

MongoDb.lib

MongoDb.dll

会用到

MongoDb.h

 

 

最后在附一个调用生成dll的代码:

// test01.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include "MongoDb.h"
#pragma comment(lib, "MongoDb.lib")

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	MongoDbOpen("127.0.0.1:27017");
	for(int i = 0 ; i < 10 ; i++)
	{
		MongoDbInsert("email << %d << address << %c",i,'a');
	}
	MongoDbSelect("email << %d",1);
	cout<<"----------------------------"<<endl;
	MongoDbRemove("email << %d",1);
	MongoDbSelect();
	cout<<"----------------------------"<<endl;
	MongoDbRemove();
	MongoDbSelect();
	cout<<"----------------------------"<<endl;
	getchar();
	return 0;
}


附件:http://download.csdn.net/detail/fuyun10036/5070192

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值