# C/C++ 快速接入
泡椒云网络验证官方提供的 C/C++ SDK,同时提供 C(C99)与 C++(C++17)两种实现, 唯一外部依赖 libcurl(+线程库),支持 Linux / macOS / Windows。
# 接入须知
# 获取方式
- 下载地址:请登录开发者后台,在首页「最新SDK」处下载
- 压缩包内容:
c/:C 版(pjysdk.h单头库 +demo.c示例)cpp/:C++ 版(pjysdk.hpp、pjysdk.cpp、内置nlohmann/json.hpp+demo.cpp示例)CMakeLists.txt:CMake 示例工程,一次构建两个 demo
# 依赖安装(libcurl)
- macOS:系统自带
- Debian/Ubuntu:
sudo apt-get install libcurl4-openssl-dev - CentOS/RHEL:
sudo yum install libcurl-devel - Windows(任选其一):
- vcpkg(MSVC):
vcpkg install curl - MSYS2 / MinGW-w64:
pacman -S mingw-w64-x86_64-curl
- vcpkg(MSVC):
线程库:Linux / macOS / MinGW 链接 -lpthread;MSVC 下 C 版自动切换为
原生 Win32 线程、C++ 版使用 std::thread,两版均可用 MSVC 直接编译。
# C 版接入
pjysdk.h 是单头库:在一个 .c 文件里定义宏再包含,即引入实现;
其余文件只 #include "pjysdk.h":
#define PJYSDK_IMPLEMENTATION
#include "pjysdk.h"
2
编译:
cc your_app.c -lcurl -lpthread -o your_app
# C++ 版接入
把 cpp/ 目录拷进你的项目(如 third_party/pjysdk/),pjysdk.cpp 加入构建,
代码里 #include "pjysdk.hpp":
c++ -std=c++17 your_app.cpp third_party/pjysdk/pjysdk.cpp \
-I third_party/pjysdk \
-lcurl -lpthread \
-o your_app
2
3
4
CMake 集成:
find_package(CURL REQUIRED)
find_package(Threads REQUIRED)
add_executable(your_app main.cpp third_party/pjysdk/pjysdk.cpp)
target_include_directories(your_app PRIVATE third_party/pjysdk)
target_link_libraries(your_app PRIVATE CURL::libcurl Threads::Threads)
2
3
4
5
6
# 调用形式与返回值
C++ 版(命名空间 pjy):
- 每个 API 返回
Resp<T>{code, message, result},code == 0表示成功; - 网络重试耗尽或服务端签名校验失败时抛出
pjy::PjyException,请用 try/catch 包裹; - 所有公开方法可并发调用。
C 版(前缀 pjy_):
- 每个 API 返回
pjy_resp,先看ok字段:ok == 0表示网络耗尽或签名校验失败 (错误描述在error);ok == 1后再看业务码code(0 为成功); result为解析后的 JSON 节点,用pjy_json_str/pjy_json_i64/pjy_json_obj读取;- 每个返回的
pjy_resp用完必须调用pjy_resp_free释放; - 所有公开函数可并发调用。
# 使用示例(C++)
#include <iostream>
#include "pjysdk.hpp"
int main() {
// 初始化 SDK,appKey 和 appSecret 在泡椒云开发者后台获取
pjy::PJYSDK sdk("AppKey", "AppSecret");
sdk.setDebug(true);
// 心跳失败回调(默认回调会打印错误并退出进程,生产环境请自行设置)
sdk.onHeartbeatFail([&sdk](const pjy::Resp<pjy::HeartbeatResult>& r) {
std::cout << "心跳失败: " << r.code << " " << r.message << std::endl;
if (r.code == 10214) {
std::exit(1); // 登录状态已失效(被挤下线等)
}
});
sdk.setDeviceID("你的设备唯一ID"); // 需自行生成,保证一机一码
sdk.setCard("卡密");
try {
// 卡密登录,成功后自动开始心跳保活
auto ret = sdk.cardLogin();
if (ret.code != 0) {
std::cout << "登录失败: " << ret.message << std::endl;
return 1;
}
std::cout << "登录成功,卡密类型: " << ret.result.cardType << std::endl;
std::cout << "剩余时间(秒): " << sdk.getTimeRemaining() << std::endl;
} catch (const pjy::PjyException& e) {
std::cout << "请求异常: " << e.what() << std::endl;
return 1;
}
// 你的业务逻辑……
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 使用示例(C)
#include <stdio.h>
#include <stdlib.h>
#define PJYSDK_IMPLEMENTATION
#include "pjysdk.h"
static void on_hb_fail(const pjy_resp *r, void *user) {
(void)user;
printf("心跳失败: %d %s\n", r->code, r->message ? r->message : "");
if (r->code == 10214) {
exit(1); /* 登录状态已失效(被挤下线等) */
}
}
int main(void) {
/* 初始化 SDK,appKey 和 appSecret 在泡椒云开发者后台获取 */
pjy_sdk *s = pjy_new("AppKey", "AppSecret");
pjy_set_debug(s, 1);
pjy_on_heartbeat_fail(s, on_hb_fail, NULL);
pjy_set_device_id(s, "你的设备唯一ID"); /* 需自行生成,保证一机一码 */
pjy_set_card(s, "卡密");
/* 卡密登录,成功后自动开始心跳保活 */
pjy_resp r = pjy_card_login(s);
if (!r.ok) {
printf("请求异常: %s\n", r.error ? r.error : "");
pjy_resp_free(&r);
pjy_free(s);
return 1;
}
if (r.code != 0) {
printf("登录失败: %s\n", r.message ? r.message : "");
pjy_resp_free(&r);
pjy_free(s);
return 1;
}
printf("登录成功,卡密类型: %s\n", pjy_json_str(r.result, "card_type"));
printf("剩余时间(秒): %d\n", pjy_get_time_remaining(s));
pjy_resp_free(&r);
/* 你的业务逻辑…… */
pjy_free(s); /* 退出时释放(内部会停止心跳线程) */
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 可更改配置
void setDebug(bool debug); // C: pjy_set_debug(s, debug)
void setAutoHeartbeat(bool enable); // C: pjy_set_auto_heartbeat(s, enable)
2
setDebug: 默认为true,开启后会在控制台输出每次请求的详细信息setAutoHeartbeat: 是否自动开启心跳,默认true,不建议修改
# 初始化
# 创建 SDK
pjy::PJYSDK sdk(appKey, appSecret); // C++(不可拷贝,可长期持有)
pjy_sdk *s = pjy_new(app_key, app_secret); // C,退出时 pjy_free(s)
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| appKey | 是 | string | 软件的 app_key,开发者后台获取 |
| appSecret | 是 | string | 软件的 app_secret,开发者后台获取 |
# 设置设备唯一 ID
void setDeviceID(const std::string& deviceID); // C++
void pjy_set_device_id(pjy_sdk *s, const char *id); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| deviceID | 是 | string | 用户设备唯一标识(长度不超过45位) |
# 设置卡密
void setCard(const std::string& card); // C++
void pjy_set_card(pjy_sdk *s, const char *card); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| card | 是 | string | 用户填写的卡密(长度不超过45位) |
# 设置用户账号
void setUser(const std::string& username, const std::string& password); // C++
void pjy_set_user(pjy_sdk *s, const char *username, const char *password); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| username | 是 | string | 用户名(长度不超过20位) |
| password | 是 | string | 用户密码(长度 6-30 位) |
# 心跳
登录成功后 SDK 自动启动心跳线程,无需手动管理。
# 心跳失败回调
void onHeartbeatFail(HeartbeatFailFn fn); // C++
void pjy_on_heartbeat_fail(pjy_sdk *s, pjy_heartbeat_fail_fn fn, void *user); // C,user 为自定义指针
2
心跳返回 code != 0 时触发。默认回调会打印错误并退出进程,生产环境请自行设置。
常见的 code == 10214 表示登录状态已失效(超时未发心跳、被挤下线、后台冻结等),
应引导用户重新登录。
# 获取心跳结果
Resp<HeartbeatResult> getHeartbeatResult(); // C++
pjy_resp pjy_get_heartbeat_result(pjy_sdk *s); // C,用完需 pjy_resp_free
2
code == 0 表示心跳正常,否则 message 包含错误信息。
# 获取剩余时长
int getTimeRemaining(); // C++
int pjy_get_time_remaining(pjy_sdk *s); // C
2
返回剩余有效秒数,不发起网络请求。
# 卡密登录
调用前需先设置卡密与设备 ID。登录成功后自动启动心跳。
Resp<CardLoginResult> cardLogin(); // C++
pjy_resp pjy_card_login(pjy_sdk *s); // C
2
返回值:成功时 result 包含 card_type(卡密类型)、expires(过期时间)、
expires_ts(过期时间戳秒)、config(自定义配置)等字段。
C++ 直接读 ret.result.cardType 等;C 用 pjy_json_str(r.result, "card_type")、
pjy_json_i64(r.result, "expires_ts") 读取。
# 卡密退出登录
Resp<Empty> cardLogout(); // C++
pjy_resp pjy_card_logout(pjy_sdk *s); // C
2
退出登录会停止心跳。
# 卡密解绑设备
需在开发者后台配置软件允许解绑,且需在卡密登录后调用。
Resp<Empty> cardUnbindDevice(); // C++
pjy_resp pjy_card_unbind_device(pjy_sdk *s); // C
2
# 卡密设置解绑密码
需在开发者后台配置软件允许解绑。该密码用于设备丢失等情况解绑。需在卡密登录后调用。
Resp<Empty> setCardUnbindPassword(const std::string& password); // C++
pjy_resp pjy_set_card_unbind_password(pjy_sdk *s, const char *password); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| password | 是 | string | 解绑密码,6-10位 |
# 卡密通过密码解绑设备
无需登录,调用前需先设置卡密。
Resp<Empty> cardUnbindDeviceByPassword(const std::string& password); // C++
pjy_resp pjy_card_unbind_device_by_password(pjy_sdk *s, const char *password); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| password | 是 | string | 解绑密码,6-10位 |
# 卡密充值(以卡充卡)
Resp<Empty> cardRecharge(const std::string& card, const std::string& useCard); // C++
pjy_resp pjy_card_recharge(pjy_sdk *s, const char *card, const char *use_card); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| card | 是 | string | 被充值的卡密 |
| useCard | 是 | string | 用于充值的卡密 |
# 用户注册(通过卡密)
调用前需先设置设备 ID。
Resp<Empty> userRegister(const std::string& username,
const std::string& password,
const std::string& card); // C++
pjy_resp pjy_user_register(pjy_sdk *s, const char *username,
const char *password, const char *card); // C
2
3
4
5
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| username | 是 | string | 用户名(不超过20位) |
| password | 是 | string | 密码(6-30位) |
| card | 是 | string | 注册使用的卡密 |
# 用户登录
调用前需先设置用户账号与设备 ID。登录成功自动心跳。
Resp<UserLoginResult> userLogin(); // C++
pjy_resp pjy_user_login(pjy_sdk *s); // C
2
# 用户退出登录
Resp<Empty> userLogout(); // C++
pjy_resp pjy_user_logout(pjy_sdk *s); // C
2
# 用户修改密码
Resp<Empty> userChangePassword(const std::string& username,
const std::string& password,
const std::string& newPassword); // C++
pjy_resp pjy_user_change_password(pjy_sdk *s, const char *username,
const char *password, const char *new_password); // C
2
3
4
5
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| username | 是 | string | 用户名 |
| password | 是 | string | 当前密码 |
| newPassword | 是 | string | 新密码(6-30位) |
# 用户充值(通过卡密)
Resp<Empty> userRecharge(const std::string& username, const std::string& card); // C++
pjy_resp pjy_user_recharge(pjy_sdk *s, const char *username, const char *card); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| username | 是 | string | 用户名 |
| card | 是 | string | 充值卡密 |
# 用户解绑设备
需在用户登录后调用。
Resp<Empty> userUnbindDevice(); // C++
pjy_resp pjy_user_unbind_device(pjy_sdk *s); // C
2
# 试用登录
调用前需先设置设备 ID。登录成功自动心跳。
Resp<TrialLoginResult> trialLogin(); // C++
pjy_resp pjy_trial_login(pjy_sdk *s); // C
2
# 试用退出登录
Resp<Empty> trialLogout(); // C++
pjy_resp pjy_trial_logout(pjy_sdk *s); // C
2
仅清除本地状态并停止心跳,无网络请求。
# 获取卡密配置
Resp<CardConfigResult> getCardConfig(); // C++,成功时 result.config 为配置内容
pjy_resp pjy_get_card_config(pjy_sdk *s); // C,pjy_json_str(r.result, "config")
2
# 更改卡密配置
Resp<Empty> updateCardConfig(const std::string& config); // C++
pjy_resp pjy_update_card_config(pjy_sdk *s, const char *config); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| config | 是 | string | 自定义配置(不超过512位) |
# 获取用户配置
Resp<UserConfigResult> getUserConfig(); // C++
pjy_resp pjy_get_user_config(pjy_sdk *s); // C
2
# 更改用户配置
Resp<Empty> updateUserConfig(const std::string& config); // C++
pjy_resp pjy_update_user_config(pjy_sdk *s, const char *config); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| config | 是 | string | 自定义配置(不超过512位) |
# 获取软件配置
Resp<SoftwareConfigResult> getSoftwareConfig(); // C++
pjy_resp pjy_get_software_config(pjy_sdk *s); // C
2
# 获取软件公告
Resp<SoftwareNoticeResult> getSoftwareNotice(); // C++,result.notice 为公告内容
pjy_resp pjy_get_software_notice(pjy_sdk *s); // C,pjy_json_str(r.result, "notice")
2
# 获取软件最新版本
Resp<SoftwareVersionResult> getSoftwareLatestVersion(const std::string& currentVer); // C++
pjy_resp pjy_get_software_latest_version(pjy_sdk *s, const char *current_ver); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| currentVer | 是 | string | 当前本地版本(不超过30位) |
成功时 result 包含 version、download_url、update_log。
# 获取远程变量
Resp<RemoteVarResult> getRemoteVar(const std::string& key); // C++
pjy_resp pjy_get_remote_var(pjy_sdk *s, const char *key); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 远程变量名(不超过64位) |
# 获取远程数据
Resp<RemoteDataResult> getRemoteData(const std::string& key); // C++
pjy_resp pjy_get_remote_data(pjy_sdk *s, const char *key); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 数据 key(不超过64位) |
# 操作远程数据
# 新增远程数据
Resp<Empty> createRemoteData(const std::string& key, const std::string& value); // C++
pjy_resp pjy_create_remote_data(pjy_sdk *s, const char *key, const char *value); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 数据 key(不超过64位) |
| value | 是 | string | 数据值(不超过256位) |
# 修改远程数据
Resp<Empty> updateRemoteData(const std::string& key, const std::string& value); // C++
pjy_resp pjy_update_remote_data(pjy_sdk *s, const char *key, const char *value); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 数据 key(不超过64位) |
| value | 是 | string | 数据值(不超过256位) |
# 删除远程数据
Resp<Empty> deleteRemoteData(const std::string& key); // C++
pjy_resp pjy_delete_remote_data(pjy_sdk *s, const char *key); // C
2
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 数据 key(不超过64位) |
# 调用远程函数
// C++:params 为 JSON 数组,返回值在 result.ret(任意 JSON)
Resp<RemoteFuncResult> callRemoteFunc(const std::string& funcName,
const nlohmann::json& params = nlohmann::json::array());
// C:params_json 为已序列化的 JSON 数组文本(NULL 视为 "[]"),返回值在 result 的 "return" 节点
pjy_resp pjy_call_remote_func(pjy_sdk *s, const char *func_name, const char *params_json);
2
3
4
5
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| funcName | 是 | string | 远程函数名(不超过64位) |
| params | 是 | JSON数组 | 参数列表,如 [1, 2] |
示例 远程函数定义(JavaScript):
function add(a, b) {
return a + b;
}
2
3
C++ 调用:
auto ret = sdk.callRemoteFunc("add", nlohmann::json::array({1, 2}));
if (ret.code == 0) {
std::cout << "计算结果: " << ret.result.ret << std::endl;
}
2
3
4
C 调用:
pjy_resp r = pjy_call_remote_func(s, "add", "[1, 2]");
if (r.ok && r.code == 0) {
printf("计算结果: %lld\n", (long long)pjy_json_i64(r.result, "return"));
}
pjy_resp_free(&r);
2
3
4
5
# 释放资源
// C++:PJYSDK 析构时自动停止心跳线程(对象离开作用域即可)
// C:退出时必须调用,内部会停止心跳线程并释放全部内存
void pjy_free(pjy_sdk *s);
2
3
提示:
- C++ 版业务状态通过
Resp<T>.code判断(0 成功),网络/签名异常抛PjyException;- C 版先看
pjy_resp.ok(0 表示网络/签名异常,见error),再看code(0 成功), 且每个pjy_resp用完必须pjy_resp_free。 返回码含义见接入须知中的对照表。
← Go 快速接入 uni-app 快速接入 →