---
code: cpp_server_sdk_installation
name: "C++"
wikiToken: D4KBwgaZjiQA3Nklwdtc9z1EnGf
parentWikiToken: O3YxwgHGiiEnvYkHCcIcX51inkf
updateTime: 1762772307000
sourceUrl: https://docs-v2.thinkingdata.cn/?version=v5.0&lan=zh-CN&code=cpp_server_sdk_installation
---
# C++

::: tip 提示

 在接入前, 请先阅读接入前准备。

 c++ 版本要求 c++ 11。需要 g++ 5.1.0 以上版本。

 :::

**最新版本**：v2.0.0

**更新时间**：2023-11-30

**资源下载：**源代码

::: warning 注意

当前文档适用于 v2.0.0 及以后的版本，历史版本请参考 C++ SDK 接入指南（V1）

::: 

### 一、集成SDK

###### Ⅰ. 编译源码，获取`libthinkingdata.a`文件

1. AE SDK 依赖 rapidjson 解析库，你需要下载 rapidjson 库到本地。
1. 下载 C++ SDK 源码，修改 SDK 中的 `CMakeLists.txt` 文件，选择你需要的数据消费者进行打包（详细内容可以参考SDK源码内的 `CMakeLists.txt` 文件）。这里以最常用的 `log``consumer` 举例：
```
cmake_minimum_required(VERSION 3.12)
project(ThinkingData)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)

message(STATUS "[${PROJECT_NAME}] current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
message(STATUS "[${PROJECT_NAME}] CMAKE_HOST_SYSTEM: ${CMAKE_HOST_SYSTEM} ")

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE release CACHE STRING "Build Type" FORCE)
endif()

message(STATUS "[${PROJECT_NAME}] Build type:${CMAKE_BUILD_TYPE}")

message(STATUS "[${PROJECT_NAME}] Debug configuration:${CMAKE_CXX_FLAGS_DEBUG}")

message(STATUS "[${PROJECT_NAME}] release configuration:${CMAKE_CXX_FLAGS_RELEASE}")

message(STATUS "[${PROJECT_NAME}] release configuration with debug info:${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")

message(STATUS "[${PROJECT_NAME}] minimal release configuration:${CMAKE_CXX_FLAGS_MINSIZEREL}")

include_directories(include)

 #
 # log consumer. Recommended for production environments
 #
 set(TE_LIB_NAME thinkingdata)
 add_library(${TE_LIB_NAME} src/TDAnalytics.cpp src/TDUtils.cpp src/TDLoggerConsumer.cpp src/TDConsumer.cpp)
 if(UNIX)
   find_package(Threads REQUIRED)
   target_link_libraries(${TE_LIB_NAME} Threads::Threads)
 endif()
```

1. rapidjson 库是一个纯 `.h` 库，所以以头文件的形式引入到你的工程。
1. 如果你的工程没有引入 rapidjson 库，那么请导入如下头文件即可：

1. 如果你的工程之前已经引入了 rapidjson 库，那么请只需导入 AE SDK 的头文件。然后需要修改并确认 `TDJsonParse.h` 文件内的内容，核对文件内对  rapidjson 库的引入路径是否正确：
###### Ⅱ. 安装Logbus

我们推荐使用SDK+LogBus的形式，完成服务端数据的采集上报.您可以参考以下文档完成Logbus的安装:LogBus使用指南

### 二、初始化

导入头文件：

```
#include "../include/TDAnalytics.h"
#include "../include/TDLoggerConsumer.h"
#include "../include/TDDebugConsumer.h"
#include "../include/TDBatchConsumer.h"

using namespace thinkingDataAnalytics;
```

以下是SDK初始化的示例代码:

```
TDLoggerConsumer::Config config = TDLoggerConsumer::Config("LOG_DIRECTORY", 20, 500, TDLoggerConsumer::*HOURLY*);
config.fileNamePrefix = "te";
config.rotateMode = TDLoggerConsumer::*HOURLY*;

TDConsumer *consumer = new TDLoggerConsumer(config);
TDAnalytics te(*consumer, false);
```

`LOG_DIRECTORY`为写入本地的文件夹地址。您只需将 LogBus 的监听文件夹地址设置为此处的地址，即可使用 LogBus 进行数据的监听上传。

### 三、常用功能

为了保证访客 ID 与账号 ID 能够顺利进行绑定，如果您的游戏中会用到访客 ID 与账号 ID，我们极力建议您同时上传这两个 ID，否则将会出现账号无法匹配的情况，导致用户重复计算，具体的 ID 绑定规则可参考用户识别规则一章。

#### 3.1 发送事件

您可以调用`track`来上传事件，建议您根据先前梳理的文档来设置事件的属性以及发送信息的条件，以下是发送事件的示例代码:

```
TDPropertiesNode event_properties;
event_properties.SetString("name1", "XZ_debug");
event_properties.SetString("name2", "logbugs");
event_properties.SetString("name3", "name3");
event_properties.SetString("#uuid", "1234567890");
event_properties.SetNumber("test_number_int", 3);
event_properties.SetNumber("test_number_double", 3.14);
event_properties.SetBool("test_bool", true);
std::string test_string = "test_string";
event_properties.SetString("test_stl_string1", test_string);
event_properties.SetDateTime("test_time1", time(nullptr), 0);
timeb t = {};
ftime(&t);
event_properties.SetDateTime("#time", t.time, t.millitm);
std::vector<std::string> test_list;
test_list.emplace_back("item11");
test_list.emplace_back("item21");
event_properties.SetList("test_list1", test_list);

// track event
te.track("accountId", "distinctId", "eventName", event_properties);
```

- 事件的名称是字符串类型，只能以字母开头，可包含数字，字母和下划线 "_"，长度最大为 50 个字符。
- Key 为该属性的名称，为字符串类型，规定只能以字母开头，包含数字，字母和下划线 "_"，长度最大为 50 个字符，对字母大小写不敏感,TE会统一转化为小写字母
- Value 为该属性的值，支持字符串、数字、布尔、时间、对象、对象组、数组
<!-- unsupported block: 34 -->

**用户属性的要求与事件属性保持一致**

#### 3.2 设置用户属性

对于一般的用户属性，您可以调用 `user_set` 来进行设置，使用该接口上传的属性将会覆盖原有的属性值，如果之前不存在该用户属性，则会新建该用户属性，类型与传入属性的类型一致，此处以设置用户名为例：

```
// user_set
TDPropertiesNode userSet_properties;
userSet_properties.SetString("userName", "test");
// 上传用户属性
te.user_set("accountId", "distinctId", userSet_properties);
```

#### 3.3 数据上报

使用 `TDLoggerConsumer` 时，采集到的事件会先转成 json 字符串，然后添加到缓存数组中。当数组元素个数超出设置的容量时才会将数据写入磁盘。默认容量限制为20条数据。

在某些业务场景下，如果您期望数据立即上报到TE服务器，可以通过调用`flush()`接口完成。需要注意，频繁调用`flush()`会导致服务性能下降。

```
te.flush();
```

#### 3.4 关闭SDK

```
te.close();
```

<!-- unsupported block: 34 -->

关闭并退出 SDK，请在关闭服务器前调用本接口，以避免缓存内的数据丢失

### 四、最佳实践

以下示例代码包含以上所有操作，我们推荐按照如下步骤使用:

```
// 导入头文件(每个平台以及IDE的路径不一样，自行适合调整)
#include "../include/TDAnalytics.h"
#include "../include/TDLoggerConsumer.h"

using namespace thinkingDataAnalytics;

TDLoggerConsumer::Config config = TDLoggerConsumer::Config("LOG_DIRECTORY", 20, 500, TDLoggerConsumer::*HOURLY*);
config.fileNamePrefix = "te";
config.rotateMode = TDLoggerConsumer::*HOURLY*;

TDConsumer *consumer = new TDLoggerConsumer(config);
TDAnalytics te(*consumer, false);

//上传事件
TDPropertiesNode event_properties;
event_properties.SetString("name1", "XZ_debug");;
event_properties.SetNumber("test_number_int", 3);
event_properties.SetBool("test_bool", true);
te.track("accountId", "distinctId", "eventName", event_properties);

//上传用户属性
TDPropertiesNode userSet_properties;
userSet_properties.SetString("userName", "test");
te.user_set("accountId", "distinctId", userSet_properties);

// 调用flush接口数据会立即写入文件，生产环境注意避免频繁调用flush引发IO或网络开销问题
// 一般情况不需要手动调用
te.flush();
```
