谷歌出品,必属精品——分享几个Google开源的C++库

谷歌出品,必属精品——分享几个Google开源的C++库

在程序员的世界里,谷歌的东西都是自带光环的。

今天跟他大家分享一下几个Google的c++开源库:

glog

breakpad

protobuf

libphonenumber

glog

在C++的世界里,尽管有很多成熟的、知名的log库,但我还是要跟你介绍一个google出品的log库,名为glog.

官网:

https://code.google.com/archive/p/google-glog/

github:

https://github.com/google/glog

The glog library implements application-level logging. This library provides logging APIs based on C++-style streams and various helper macros.

主要功能:

1, 参数设置,以命令行参数的方式设置标志参数来控制日志记录行为;

2, 严重性分级,根据日志严重性分级记录日志;

3, 可有条件地记录日志信息;

4, 条件中止程序。丰富的条件判定宏,可预设程序终止条件;

5, 异常信号处理。程序异常情况,可自定义异常处理过程;

6, 支持debug功能。可只用于debug模式;

7, 自定义日志信息;

8, 线程安全日志记录方式;

9, 系统级日志记录;

10, google perror风格日志信息;

11, 精简日志字符串信息。

glog在vs2010下编译

打开google-glog.sln

编译

成功

在Debug文件夹下就有我们想要的libglog.dll libglog.lib等我们想要的文件

glog在vs2013下编译

打开google-glog.sln

编译

错误:’min’不是std的成员

谷歌出品,必属精品——分享几个Google开源的C++库

解决方法:

添加头文件#include<algorithm>

重新编译

成功

在Debug文件夹下就有我们想要的libglog.dll libglog.lib等我们想要的文件

glog在vs2015下编译

打开google-glog.sln

编译

错误1:’min’不是std的成员

解决方法:

添加头文件#include<algorithm>

错误2:warning C4005: “va_copy”: 宏重定义

解决方法:

修改文件port.h,117行改为:

#undef va_copy#define va_copy(dst, src) (dst) = (src)

错误3:

error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体

c:\program files (x86)\windows kits\10\include\10.0.10150.0\\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义

解决方案:

修改snprintf的名字,比如改为snprintf_glog,记得所有的都要改

错误4:

d:\glog\glog-0.3.3\src\windows\glog\logging.h(1264): error C2280: “std::basic_ios

#define GLOG_NO_ABBREVIATED_SEVERITIES 
#include <windows.h> 
#include "glog/logging.h"
using namespace google;
int main(int argc, char* argv[]) { 
 google::InitGoogleLogging("test"); 
 google::SetLogDestination(google::GLOG_INFO, "../Debug/logtestInfo"); 
 google::SetLogDestination(google::GLOG_ERROR, "../Debug/logtestDebug");//不为ERROR建立日志文件 
 int num_cookies = 0; 
 google::SetStderrLogging(google::GLOG_INFO); 
 google::SetStderrLogging(google::GLOG_ERROR); //google::LogToStderr(); 
 for (int i = 0; i < 100; ++i) { 
 LOG(INFO) << "test google glog" << i << " cookies"; 
 } 
 google::ShutdownGoogleLogging();
}

可能发生的错误:

Error 2 error LNK2005: “public: __thiscall std::_Container_base12::_Container_base12(void)” (??0_Container_base12@std@@QAE@XZ) already defined in msvcprtd.lib(MSVCP120D.dll) D:\test\test_google_glog_vs2013\test_google_glog_vs2013\main.obj test_google_glog_vs2013

这个错误,是因为在编译库glog的时候,选择的代码生成方式和现在工程的代码生成方式不一样:

谷歌出品,必属精品——分享几个Google开源的C++库

Breakpad

什么是Google Breakpad?

Google Breakpad is a cross platform crash handler which generates minidumps when your application crash. Users can send these minidumps to you and it contains valuable information allowing you to figure out why it crashed on them.

看到了吗?是当你程序崩溃的时候产生一个minidumps文件的,之前我们也写过两篇博客:

《windows客户端开发–让你的客户端崩溃之前生成dump文件》

《Qt–让你的客户端崩溃之前生成dump文件》

获取BreakPad

git clone https://chromium.googlesource.com/breakpad/breakpad

安装Python

这里面略过了,但是记住要使用Python2.x,,Python3.x会报错

什么是gyp

GYP(Generate Your Projects)是由 Chromium 团队开发的跨平台自动化项目构建工具,Chromium 便是通过 GYP 进行项目构建管理。

获取gyp

git clone https://chromium.googlesource.com/external/gyp

安装gyp

cd gyppython setup.py install

谷歌出品,必属精品——分享几个Google开源的C++库

拷贝gyp文件夹到breakpad\src\tools文件夹下

谷歌出品,必属精品——分享几个Google开源的C++库

生成Breakpad的sln文件

进入刚刚拷贝的gyp目录,然后执行:

gyp.bat –no-circular-check “../../client/windows/breakpad_client.gyp”

wangs@LAPTOP-MNU6522J MINGW64 /d/chromium/src/breakpad/src/tools/gyp (master)$ gyp.bat --no-circular-check "../../client/windows/breakpad_client.gyp"Warning: Missing input files:..\..\client\windows\\unittests\..\..\..\testing\src\gmock-all.cc..\..\client\windows\\unittests\..\..\..\testing\gtest\src\gtest-all.cc..\..\client\windows\\unittests\..\..\..\testing\src\gmock_main.cc12345671234567

这里要注意,一定不能使用绝对路径,要使用相对路径,所以为什么要拷贝gyp文件夹到tools文件夹下面。

谷歌出品,必属精品——分享几个Google开源的C++库

使用vs2015编译

刚才我看看到了提示,missing几个文件,所以我们这里不能编译unittest下的两个工程,暂时不理会

谷歌出品,必属精品——分享几个Google开源的C++库

错误:

2>C:\Program Files (x86)\Windows Kits\8.1\Include\\um\dbghelp.h(1544): error C2220: 警告被视为错误 - 没有生成“object”文件

2>C:\Program Files (x86)\Windows Kits\8.1\Include\\um\dbghelp.h(1544): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧

2>C:\Program Files (x86)\Windows Kits\8.1\Include\\um\dbghelp.h(3190): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧

4>C:\Program Files (x86)\Windows Kits\8.1\Include\\um\dbghelp.h(1544): error C2220: 警告被视为错误 - 没有生成“object”文件

4>C:\Program Files (x86)\Windows Kits\8.1\Include\\um\dbghelp.h(1544): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧

4>C:\Program Files (x86)\Windows Kits\8.1\Include\\um\dbghelp.h(3190): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧

解决方案,把警告当错误 选择否。

编译后,在debug文件夹下:

谷歌出品,必属精品——分享几个Google开源的C++库

使用Breakpad生成dump文件

前戏有点复杂,现在开始使用。把之前生成的几个lib,包含进来

common.lib

exception_handler.lib

crash_generation_server.lib

crash_generation_client.lib

头文件目录导进来:

谷歌出品,必属精品——分享几个Google开源的C++库

编写代码:

#include <cstdio>

#include "client/windows/handler/exception_handler.h"

namespace {

static bool callback(const wchar_t *dump_path, const wchar_t *id,

void *context, EXCEPTION_POINTERS *exinfo,

MDRawAssertionInfo *assertion,

bool succeeded) {

if (succeeded) {

printf("dump guid is %ws\n", id);

}

else {

printf("dump failed\n");

}

fflush(stdout);

return succeeded;

}

static void CrashFunction() {

int *i = reinterpret_cast<int*>(0x45);

*i = 5; // crash!

}

} // namespace

int main(int argc, char **argv) {

google_breakpad::ExceptionHandler eh(

L".", NULL, callback, NULL,

google_breakpad::ExceptionHandler::HANDLER_ALL);

CrashFunction();

printf("did not crash?\n");

return 0;

}

可能的错误:

common.lib(guid_string.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(main.obj 中)

解决方法:

就是编译库的时候 和现在使用库的工程 选择的代码生成方式不一致:

谷歌出品,必属精品——分享几个Google开源的C++库

如何根据生成的dump定位错误代码

文件->打开->文件,找到刚生成的dump文件,然后点击“使用仅限本机进行调试”

谷歌出品,必属精品——分享几个Google开源的C++库

结果:

谷歌出品,必属精品——分享几个Google开源的C++库

准确定位!!!!

protobuf

本想用google的libphonenumber这个库来进行电话号相关功能,但是看到需要依赖protobuf,反正都是谷歌出品,那就顺便了解学习一下protobuf。

github地址:

https://github.com/google/protobuf

什么是protobuf

Protocol Buffers (a.k.a., protobuf) are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data. You can find protobuf’s documentation on the Google Developers site.

protocolbuffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:Java、c#、c++、go 和 Python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。

下载带vsprojects的版本

我们需要下载带vsprojects的版本,所以不需要太新的,我们要下载2.6

https://github.com/google/protobuf/releases?after=v3.0.0-alpha-3

下载后解压,就可以看到有一个叫vsprojects的文件夹了。

使用vs2015编译

可以使用vs2010编译的,相对简单一些,但我们使用vs2015.

1打开sln

谷歌出品,必属精品——分享几个Google开源的C++库

2编译错误以及解决

错误1:

error C2338: is deprecated and will be REMOVED. Please use . You can define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS to acknowledge that you have received this warning.

解决方法:

添加预编译:

_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS

谷歌出品,必属精品——分享几个Google开源的C++库

错误2:

如果要将多个 CL.EXE 写入同一个 .PDB 文件,请使用 /FS

解决方法:

添加命令行 /FS

谷歌出品,必属精品——分享几个Google开源的C++库

错误3:

error C3688: 文本后缀“PATH_SEPARATOR”无效;未找到文文本运算符或文本运算符模板“operator “”“”PATH_SEPARATOR”

解决方案:

Run(“protocol_compiler –test_out=tmpdir”“–protopath=tmpdir/a"PATH_SEPARATOR"tmpdir/bfoo.proto”);改为Run(“protocolcompiler–testout=tmpdir ”

“–proto_path=tmpdir/a"";""tmpdir/b foo.proto”);

错误4:

error C3688: 文本后缀“ETC”无效;未找到文文本运算符或文本运算符模板“operator “”“”ETC”

解决方案:

注释掉整个TEST_F(ParseMessageTest, FieldDefaults)

就是宏定义有问题,在vs2015中,具体什么原因还需要进一步研究!!!!!

使用protobuf

1 在D:\protobuf-2.6.1\examples下新建一个文件,姑且就叫person.proto,

键入内容:

package tutorial; 
message Person { 
 required string name = 1; 
 required int32 age = 2; 
 optional string email = 3; 
}

然后执行命令:

D:\protobuf-2.6.1\vsprojects\Release>protoc -I=D:\protobuf-2.6.1\examples --cpp_out=D:\protobuf-2.6.1\examples D:\protobuf-2.6.1\examples\person.proto

生成了 person.pb.h和person.pb.cc

2新建一个工程

配置:

附加包含目录,导入这个路径D:\protobuf-2.6.1\src

链接器 的常规,右边的附加库目录,导入这个路径D:\protobuf-2.6.1\vsprojects\Release

讲person.pb.h和person.pb.cc添加到自己的工程中

然后键入测试代码:

#include <iostream>

#include "person.pb.h"

#pragma comment(lib, "libprotobuf.lib")

#pragma comment(lib, "libprotoc.lib")

using namespace std;

using name space tutorial;

int main(){

Person person;

person.set_name("wangshubo");

person.set_age(26);

person.set_email("[email protected]");

cout << person.name() << endl;

cout << person.age() << endl;

cout << person.email() << endl;

system("pause");

return0;

}

提示:

如果出现Person无法解析,很有可能是只包含了头文件,没有把.cc实现文件也包含进来。

在新建protobuf文件的时候,用windows自带的记事本就可以了,需要的是ANSI,不可以是Unicode

libphonenumber

虽然这个库是用c++写的,但是我们在网络上很少见到在C++开发中使用这个库,或是说在windows开发中使用这个库。也就是几乎很难找到如何编译libphonenumber.lib 和 libphonenumber.dll.

所以,今天就要与大家分享一下,如何编译libphonenumber.lib,以及简单的使用。

libphonenumber简介

phonenumber是用于解析、格式化、存储和校验电话号码的Java、C++或 JavaScript类库。

Google’s common Java, C++ and JavaScript library for parsing, formatting, and validating international phone numbers. The Java version is optimized for running on smartphones, and is used by the Android framework since 4.0 (Ice Cream Sandwich).

github地址:

https://github.com/googlei18n/libphonenumber

准备工作

我们先进入cpp:

https://github.com/googlei18n/libphonenumber/tree/master/cpp

看看这里的README,往下翻,你会感到很兴奋:

Building the library on Windows (Visual Studio)

-----------------------------------------------

The library was tested with Visual Studio 2010.

You will need to manually fetch and install the following dependencies:

- CMake (tested with v2.8.6):

http://cmake.org/cmake/resources/software.html

* Download and install the Win32 installer.

- Boost (tested with v1.44) from BoostPro:

http://www.boostpro.com/download/

* Select all the variants and Boost DateTime and Boost Thread during the

installation process.

See Linux instructions for information about thread-safety.

- GTest (tested with v1.6.0):

http://code.google.com/p/googletest/downloads/list

* Open msvc/gtest-md.sln with Visual Studio and build the whole solution.

- ICU (MSVC binaries, tested with v4.8.1):

http://site.icu-project.org/download/48#ICU4C-Download

* Simply extract the archive.

- Protocol Buffers:

http://code.google.com/p/protobuf/downloads/list

* Open vsprojects/protobuf.sln with Visual Studio and build the whole

solution.

Then run cmake-gui and specify the path to the libphonenumber's cpp directory

and its build directory which must be created (e.g. cpp/build).

When clicking on "Configure", specify the appropriate Visual Studio version

(tested with 2010).

Then CMake will need your help to locate the dependencies. You will have to set

the following variables (this example assumes that you extracted the

dependencies to C:/).

GTEST_INCLUDE_DIR C:/gtest-1.6.0/include

GTEST_LIB C:/gtest-1.6.0/msvc/gtest-md/Release/gtest.lib

ICU_I18N_INCLUDE_DIR C:/icu/include

ICU_I18N_LIB C:/icu/lib/icuin.lib

ICU_UC_INCLUDE_DIR C:/icu/include

ICU_UC_LIB C:/icu/lib/icuuc.lib

PROTOBUF_INCLUDE_DIR C:/protobuf-2.4.1/src

PROTOBUF_LIB C:/protobuf-2.4.1/vsprojects/Release/libprotobuf.lib

PROTOC_BIN C:/protobuf-2.4.1/vsprojects/Release/protoc.exe

Then you can click on "Configure" again. CMake should have located all the

dependencies.

Then click on "Generate" to generate the appropriate Visual Studio project.

Then open cpp/build/libphonenumber.sln with Visual Studio and build the INSTALL

target.

As a result the library's headers and binaries should have been installed to

C:/Program Files/libphonenumber/.

Note that this path can be set by overriding the CMAKE_INSTALL_PREFIX variable

with cmake-gui.

Supported build parameters

--------------------------

Build parameters can be specified invoking CMake with '-DKEY=VALUE' or using a

CMake user interface (ccmake or cmake-gui).

USE_ALTERNATE_FORMATS = ON | OFF [ON] -- Use alternate formats for the phone

number matcher.

USE_BOOST = ON | OFF [ON] -- Use Boost. This is only needed in

multi-threaded environments that

are not Linux and Mac.

Libphonenumber relies on Boost for

non-POSIX (e.g. Windows)

multi-threading.

USE_ICU_REGEXP = ON | OFF [ON] -- Use ICU regexp engine.

USE_LITE_METADATA = ON | OFF [OFF] -- Generates smaller metadata that

doesn't include example numbers.

USE_RE2 = ON | OFF [OFF] -- Use RE2.

USE_STD_MAP = ON | OFF [OFF] -- Force the use of std::map.

1 cmake

对于cmake不太了解的同志,就跟我一样好了,下载一个cmake-gui

https://cmake.org/

2 Boost

2.1下载

http://www.boost.org/

2.2解压

解压到C盘boost_1_62_0

2.3执行

执行bootstrap.bat

2.4执行

// 如果要获取动态库:bjam install stage --toolset=msvc-14.0 --stagedir="C:\Boost\boost_vc_140" link=shared runtime-link=shared threading=multi debug release 
// 如果是要获取静态库:bjam install stage --toolset=msvc-14.0 --stagedir="C:\Boost\boost_vc_140" link=static runtime-link=static threading=multi debug release

3 GTest

下载gtest,然后进入文件夹:

D:\gtest\googletest\googletest\msvc

打开解决方案,就可以编译了。

4 ICU

这里的icu不是重症监护室,但是下载icu需要vpn翻墙,你懂的。

下载地址:

http://download.icu-project.org/files/icu4c/4.8.1.1/

这里注意,尽管你的windows电脑是64位,但是你开发的往往是32位程序,所以需要下载win23:

谷歌出品,必属精品——分享几个Google开源的C++库

解压到C盘即可。

5 Protocol Buffers

这个就不用再说了,上一篇博客就是关于《google/protobuf–VS2015编译、使用》

准备工作齐活了,开始干大事。

生成libphonenumber解决方案

1 在cpp文件夹在新建一个文件夹,叫build。

2 打开cmake-gui,选择cpp文件夹作为source code, 选择build文件夹作为目标文件夹,然后添加一些变量,指向自己的路径即可:

谷歌出品,必属精品——分享几个Google开源的C++库

这里需要注意的是,如果boost的错误太多,可以暂时把USE_BOOST去掉。

3 Configure

出现在这个,算是没毛病

Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)Configuring done

4 点击 Generate

在build文件夹下就会看到产生的.sln解决方案文件。

编译libphonenumber

打开解决方案,配置一些路径就可以了:

谷歌出品,必属精品——分享几个Google开源的C++库

这里需要注意的是,可以由于各种原因,不能所有的build成功,主要确保phonenumber这个工程编译成功即可。

使用libphonenumber

终于搞定了,我们现在就使用一下这个牛逼的库吧。

1 新建一个win32控制台应用程序

2 加入头文件,包含目录

谷歌出品,必属精品——分享几个Google开源的C++库

3 添加引用库

谷歌出品,必属精品——分享几个Google开源的C++库

编写代码:

#include<iostream>

#include<string>

#include "phonenumber.h"

#include "phonenumberutil.h"

using i18n::phonenumbers::PhoneNumberUtil;

using i18n::phonenumbers::PhoneNumber;

int main()

{

PhoneNumberUtil *phoneUtil = PhoneNumberUtil::GetInstance();

PhoneNumber *pn = new PhoneNumber();

pn->set_country_code(86);

pn->set_national_number(13478808311);

std::cout << std::boolalpha << phoneUtil->IsValidNumber(*pn) << std::endl;

std::string *region = new std::string();

phoneUtil->GetRegionCodeForNumber(*pn, region);

std::cout << *region << std::endl;

std::string* name = new std::string();

phoneUtil->GetNationalSignificantNumber(*pn, name);

std::cout << *name << std::endl;

PhoneNumber *example = new PhoneNumber();

phoneUtil->GetInvalidExampleNumber("CN", example);

std::cout << example->country_code() << std::endl;

//释放内存

delete pn;

pn = nullptr;

delete region;

region = nullptr;

delete name;

name = nullptr;

delete example;

example = nullptr;

system("pause");

return 0;

}

输出:

true
CN
13478808311
86

注意:

在生成库的时候,和我们编写自己的工程的时候,一定要选择一致的代码生成方式!!!!!!

结束:

大概就这样了,其实自己走的弯路、遇到的错误,比上面所写的多的多,但是很多都忘记了。

如果你遇到什么错误,可以给我留言,帮你解决,谢谢。

谷歌出品,必属精品——分享几个Google开源的C++库

相关推荐