跳到主要内容

C++ SDK 快速集成

WebGLHost C++ SDK 提供了标准的 C++ 接口,用于在 Windows 和 macOS 桌面应用中集成和管理 WebGL 游戏小程序。

1. 获取凭据​

集成 SDK 需要先在 小游戏宿主控制台 中创建应用,获得每个应用专属的 APP KEY, APP SECRET 及 Service Token 后。 启动 SDK 时,需要通过 APP KEY,APP SECRET 初始化。接入方也可联系 Unity 以创建 App Service Token / App Key / App Secret。

如下是测试用 App Service Token / App Key / App Secret 示例

  • App Service Token
  • App Key: AKIDt1vMSYVFf1twI53iDecobx6QsTK0
  • App Secret: ufzN1iD8PsnMW0ViDCMhpJFBiLR1E1Xf

Service Token 的主要作用是调用以下 API 获取游戏列表,并可从中获取 Game ID 和 Launch Key 以启动游戏。

使用令牌获取小游戏列表

1.1 关键 ID 说明​

在集成 SDK 时,需要理解以下几个关键标识符:

标识符说明来源
Game ID (Applet ID)游戏的唯一标识符,用于 LaunchApplet 和 CloseApplet 的第一个参数游戏列表 API 返回的 id 字段
Launch Key游戏启动 Key,用于 launchConfig 中的 launchKey 字段游戏列表 API 返回的 launchKey 字段
Host App ID宿主应用的唯一标识符,用于获取游戏列表在控制台创建应用时获得
Access Token用户访问令牌,用于身份验证由宿主应用的用户系统提供

游戏列表 API 返回示例:

[
{
"id": "691acb162dcfadc65a0fdb77", // Game ID - 用于 LaunchApplet 第一个参数
"appId": "691ac9ef2dcfadc65a0fb4a6", // Host App ID
"name": "示例游戏",
"launchKey": "691acb162dcfadc65a0fdb77", // Launch Key - 用于 launchConfig
"gameType": "webgl",
"briefIntro": "这是一个示例游戏"
}
]

实际生产环境中,Service Token 应该在服务端使用,从服务端调用上面的 API 。Demo 项目中,Service Token 是在客户端使用,这个仅仅是一个实例,不建议在生产环境中这样使用。

2. 获取 SDK​

2.1 下载 SDK​

从 PC SDK 下载页面 下载最新的 C++ SDK 包。

2.2 获取 Demo 项目​

完整的 C++ SDK Demo 项目可从 GitHub 获取:

GitHub 仓库: https://github.com/UnityMiniHost/PCDemo

# 克隆 Demo 项目
git clone https://github.com/UnityMiniHost/PCDemo.git
cd PCDemo

SDK Demo 项目包含以下内容:

PCDemo_cpp/
├── include/ # SDK 头文件
│ ├── IBrowsingService.h # 主服务接口
│ ├── IAppletManagerV3.h # 游戏管理接口
│ ├── ICoreServiceHandler.h # 事件处理接口
│ └── WIUnknown.h # 基础接口
├── native_sdk/ # 预打包的 SDK 和运行时
│ ├── windows/ # Windows 平台
│ │ ├── host.zip # SDK DLL (webglhost_export.dll)
│ │ ├── runtime.z01 # 运行时分卷压缩包 (part 1)
│ │ ├── runtime.z02 # 运行时分卷压缩包 (part 2)
│ │ ├── runtime.z03 # 运行时分卷压缩包 (part 3)
│ │ └── version.json # 版本信息
│ └── mac/ # macOS 平台
│ ├── runtime-x64.tar.gz.01 # x64 运行时分卷压缩包 (part 1)
│ ├── runtime-x64.tar.gz.02 # x64 运行时分卷压缩包 (part 2)
│ ├── runtime-x64.tar.gz.03 # x64 运行时分卷压缩包 (part 3)
│ ├── runtime-arm64.tar.gz.01 # ARM64 运行时分卷压缩包 (part 1)
│ ├── runtime-arm64.tar.gz.02 # ARM64 运行时分卷压缩包 (part 2)
│ ├── runtime-arm64.tar.gz.03 # ARM64 运行时分卷压缩包 (part 3)
│ └── version.json # 版本信息
├── demo.cpp # 示例代码
├── CMakeLists.txt # CMake 构建配置
├── scripts/ # 构建和运行脚本
│ ├── build.bat # Windows 构建脚本
│ ├── build.sh # macOS 构建脚本
│ ├── build-and-run.bat # Windows 一键构建运行
│ ├── build-and-run.sh # macOS 一键构建运行
│ ├── clean.bat # Windows 清理脚本
│ ├── clean.sh # macOS 清理脚本
│ ├── pack.bat # Windows 打包脚本
│ ├── pack.sh # macOS 打包脚本
│ ├── run.bat # Windows 运行脚本
│ ├── run.sh # macOS 运行脚本
│ └── USAGE.md # 脚本使用说明
├── docs/ # 文档
│ ├── Quick-Start-Guide.md # 快速开始指南
│ └── API-Integration-Guide.md # API 集成指南
└── README.md # 项目说明

**注意**:
- SDK 和运行时文件已预先打包在 `native_sdk/` 目录中
- 使用分卷压缩以适应 Git 仓库大小限制
- 构建脚本会自动解压这些文件到正确的位置
- Windows: `webglhost_export.dll` 和 `webglhost-runtime.exe`
- macOS: `libwebglhost_export.dylib` 和 `webglhost-runtime.app`

3. 快速开始​

3.1 添加头文件​

将 include/ 目录添加到项目的包含路径:

#include "IBrowsingService.h"
#include "IAppletManagerV3.h"
#include "ICoreServiceHandler.h"

3.2 配置项目​

CMake 配置:

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 添加头文件路径
include_directories(${CMAKE_SOURCE_DIR}/include)

# 链接库 (Windows)
if(WIN32)
target_link_libraries(your_app ws2_32)
endif()

Visual Studio 项目配置 (Windows):

  1. 项目属性 → C/C++ → 常规 → 附加包含目录: 添加 include 路径
  2. 项目属性 → 链接器 → 输入 → 附加依赖项: 添加 ws2_32.lib
  3. 项目属性 → C/C++ → 语言 → C++ 语言标准: ISO C++17 标准

Xcode 项目配置 (macOS):

  1. Build Settings → Header Search Paths: 添加 include 路径
  2. Build Settings → C++ Language Dialect: C++17
  3. 不需要额外链接库(系统框架自动链接)

3.3 加载 SDK​

Windows:

#include <windows.h>
#include "IBrowsingService.h"

// Load DLL
HMODULE hDll = LoadLibraryA("host\\webglhost_export.dll");
if (!hDll) {
std::cerr << "Failed to load DLL" << std::endl;
return 1;
}

// Get factory function
typedef IBrowsingService* (*GetBrowsingServiceFunc)();
GetBrowsingServiceFunc GetBrowsingService =
(GetBrowsingServiceFunc)GetProcAddress(hDll, "GetBrowsingService");

if (!GetBrowsingService) {
std::cerr << "Failed to get GetBrowsingService function" << std::endl;
FreeLibrary(hDll);
return 1;
}

// Get service instance
IBrowsingService* service = GetBrowsingService();

macOS:

#include <dlfcn.h>
#include "IBrowsingService.h"

// Load dylib
void* hDll = dlopen("host/libwebglhost_export.dylib", RTLD_LAZY);
if (!hDll) {
std::cerr << "Failed to load dylib: " << dlerror() << std::endl;
return 1;
}

// Get factory function
typedef IBrowsingService* (*GetBrowsingServiceFunc)();
GetBrowsingServiceFunc GetBrowsingService =
(GetBrowsingServiceFunc)dlsym(hDll, "GetBrowsingService");

if (!GetBrowsingService) {
std::cerr << "Failed to get GetBrowsingService function: " << dlerror() << std::endl;
dlclose(hDll);
return 1;
}

// Get service instance
IBrowsingService* service = GetBrowsingService();

3.4 初始化 SDK​

// Configuration
const char* SDK_KEY = "your-sdk-key";
const char* SDK_SECRET = "your-sdk-secret";

// Build config JSON
char config[1024];
snprintf(config, sizeof(config), R"({
"sdkKey": "%s",
"sdkSecret": "%s",
"debug": true
})", SDK_KEY, SDK_SECRET);

// Initialize (runtime_path: empty for auto-detection)
int result = service->InitializeBrowsingCore(config, "", nullptr);

if (result == WMPF_ERRCODE_SUCCESS) {
std::cout << "SDK initialized successfully!" << std::endl;
} else {
std::cerr << "SDK initialization failed: " << result << std::endl;
return 1;
}

3.5 获取游戏管理器​

// Query IAppletManagerV3 interface
IAppletManagerV3* appletMgr = nullptr;
result = service->QueryInterface("IAppletManagerV3", (void**)&appletMgr);

if (result != WMPF_ERRCODE_SUCCESS || !appletMgr) {
std::cerr << "Failed to get IAppletManagerV3" << std::endl;
return 1;
}

std::cout << "Got IAppletManagerV3 interface" << std::endl;

3.6 启动游戏​

// Launch callback
void OnLaunchComplete(const char* app_id, int result_code, const char* error_desc) {
if (result_code == WMPF_ERRCODE_SUCCESS) {
std::cout << "Game launched successfully: " << app_id << std::endl;
} else {
std::cerr << "Game launch failed: " << error_desc << std::endl;
}
}

// Game configuration
// APPLET_ID: 来源于游戏列表 API 返回的 "id" 字段
// LAUNCH_KEY: 来源于游戏列表 API 返回的 "launchKey" 字段
const char* APPLET_ID = "691acb162dcfadc65a0fdb77"; // 从游戏列表获取
const char* LAUNCH_KEY = "691acb162dcfadc65a0fdb77"; // 从游戏列表获取
const char* ACCESS_TOKEN = "your-access-token";

// Build launch config
// launchKey 必须使用从游戏列表 API 获取
char launchConfig[2048];
snprintf(launchConfig, sizeof(launchConfig), R"({
"launchKey": "%s",
"accessToken": "%s",
"userId": "developer",
"debug": true,
"mute": false
})", LAUNCH_KEY, ACCESS_TOKEN);

// Launch the game
// 第一个参数 APPLET_ID 是游戏列表 API 返回的 "id" 字段
appletMgr->LaunchApplet(
APPLET_ID,
launchConfig,
strlen(launchConfig),
OnLaunchComplete
);

std::cout << "Game launch request sent..." << std::endl;

3.7 清理资源​

// Wait for game to finish (in real app, use event loop)
std::this_thread::sleep_for(std::chrono::seconds(60));

// Close game
appletMgr->CloseApplet(APPLET_ID);

// Cleanup
appletMgr->Release();
service->UninitializeBrowsingCore();
service->Release();

// Unload library
#ifdef _WIN32
FreeLibrary(hDll);
#else
dlclose(hDll);
#endif

std::cout << "Cleanup complete" << std::endl;

4. 完整最小示例​

#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include "IBrowsingService.h"
#include "IAppletManagerV3.h"

// SDK Configuration
const char* SDK_KEY = "AKIDcv9N9wkDXKZ7gDoB2avKlu0N8tnS";
const char* SDK_SECRET = "sp9ZsGlNLmTSX9o0sa29C5FwmxemUV8A";
const char* ACCESS_TOKEN = "w2uAAaGN0WOdmNiNLcKQML4JT3O-5ng2hx2Mur_1dvY01ef";

// Game Configuration - 这些值应该从游戏列表 API 获取
// APPLET_ID: 游戏列表 API 返回的 "id" 字段
// LAUNCH_KEY: 游戏列表 API 返回的 "launchKey" 字段
const char* APPLET_ID = "691acb162dcfadc65a0fdb77";
const char* LAUNCH_KEY = "691acb162dcfadc65a0fdb77";

// Global state
std::atomic<bool> g_launchCompleted{false};
std::atomic<int> g_launchResultCode{-1};

// Launch callback
void OnLaunchComplete(const char* app_id, int result_code, const char* error_desc) {
g_launchResultCode = result_code;
g_launchCompleted = true;

if (result_code == WMPF_ERRCODE_SUCCESS) {
std::cout << "Game launched: " << app_id << std::endl;
} else {
std::cerr << "Launch failed: " << (error_desc ? error_desc : "Unknown error") << std::endl;
}
}

int main() {
// 1. Load library
#ifdef _WIN32
HMODULE hDll = LoadLibraryA("host\\webglhost_export.dll");
if (!hDll) {
std::cerr << "Failed to load DLL" << std::endl;
return 1;
}
typedef IBrowsingService* (*GetBrowsingServiceFunc)();
GetBrowsingServiceFunc GetBrowsingService =
(GetBrowsingServiceFunc)GetProcAddress(hDll, "GetBrowsingService");
#else
void* hDll = dlopen("host/libwebglhost_export.dylib", RTLD_LAZY);
if (!hDll) {
std::cerr << "Failed to load dylib: " << dlerror() << std::endl;
return 1;
}
typedef IBrowsingService* (*GetBrowsingServiceFunc)();
GetBrowsingServiceFunc GetBrowsingService =
(GetBrowsingServiceFunc)dlsym(hDll, "GetBrowsingService");
#endif

if (!GetBrowsingService) {
std::cerr << "Failed to get GetBrowsingService" << std::endl;
return 1;
}

// 2. Get service instance
IBrowsingService* service = GetBrowsingService();
if (!service) {
std::cerr << "Failed to get service instance" << std::endl;
return 1;
}

// 3. Initialize SDK
char config[1024];
snprintf(config, sizeof(config), R"({
"sdkKey": "%s",
"sdkSecret": "%s",
"debug": true
})", SDK_KEY, SDK_SECRET);

std::cout << "Initializing SDK..." << std::endl;
int result = service->InitializeBrowsingCore(config, "", nullptr);

if (result != WMPF_ERRCODE_SUCCESS) {
std::cerr << "Init failed: " << result << std::endl;
return 1;
}
std::cout << "SDK initialized" << std::endl;

// 4. Get applet manager
IAppletManagerV3* appletMgr = nullptr;
result = service->QueryInterface("IAppletManagerV3", (void**)&appletMgr);

if (result != WMPF_ERRCODE_SUCCESS || !appletMgr) {
std::cerr << "Failed to get IAppletManagerV3" << std::endl;
return 1;
}
std::cout << "Got IAppletManagerV3" << std::endl;

// 5. Launch game
// launchKey 来源于游戏列表 API 返回的 "launchKey" 字段
char launchConfig[2048];
snprintf(launchConfig, sizeof(launchConfig), R"({
"launchKey": "%s",
"accessToken": "%s",
"userId": "developer",
"debug": true
})", LAUNCH_KEY, ACCESS_TOKEN);

std::cout << "Launching game..." << std::endl;
// APPLET_ID 来源于游戏列表 API 返回的 "id" 字段
appletMgr->LaunchApplet(APPLET_ID, launchConfig, strlen(launchConfig), OnLaunchComplete);

// 6. Wait for launch
while (!g_launchCompleted) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

if (g_launchResultCode != WMPF_ERRCODE_SUCCESS) {
std::cerr << "Game launch failed, exiting..." << std::endl;
appletMgr->Release();
service->UninitializeBrowsingCore();
service->Release();
return 1;
}

// 7. Keep running
std::cout << "\nGame is running. Press Ctrl+C to exit..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(60));

// 8. Cleanup
std::cout << "\nClosing game..." << std::endl;
appletMgr->CloseApplet(APPLET_ID);

appletMgr->Release();
service->UninitializeBrowsingCore();
service->Release();

#ifdef _WIN32
FreeLibrary(hDll);
#else
dlclose(hDll);
#endif

std::cout << "Done!" << std::endl;
return 0;
}

5. 编译和运行​

Demo 项目提供了便捷的脚本来自动解压 SDK、构建和运行示例程序。

5.1 Windows​

一键构建并运行:

cd scripts
build-and-run.bat

分步操作:

cd scripts

REM 1. 构建项目(自动解压 SDK 和运行时)
build.bat

REM 2. 运行示例
run.bat

REM 3. 清理构建产物
clean.bat

使用 CMake 手动构建:

# 首先需要手动解压 native_sdk/windows/ 下的文件

mkdir build
cd build
cmake .. -G "Visual Studio 16 2019" -A x64
cmake --build . --config Release
.\Release\demo.exe

5.2 macOS​

一键构建并运行:

cd scripts
chmod +x *.sh
./build-and-run.sh

分步操作:

cd scripts
chmod +x *.sh

# 1. 构建项目(自动解压 SDK 和运行时)
./build.sh

# 2. 运行示例
./run.sh

# 3. 清理构建产物
./clean.sh

使用 CMake 手动构建:

# 首先需要手动解压 native_sdk/mac/ 下的文件

mkdir build
cd build
cmake ..
make
./demo

构建脚本说明:

  • 构建脚本会自动检测系统架构(x64 或 ARM64)
  • 自动合并和解压分卷压缩包
  • 将 SDK 和运行时文件放置到正确的位置
  • 详细说明请参考 scripts/USAGE.md

6. 系统要求​

6.1 Windows​

  • 操作系统: Windows 10/11 (64位)
  • 开发工具: Visual Studio 2019 或更高版本
  • C++ 标准: C++17 或更高
  • 依赖库: ws2_32.lib (Windows Sockets)

6.2 macOS​

  • 操作系统: macOS 10.15+ (Catalina 或更高版本)
  • 开发工具: Xcode Command Line Tools
  • C++ 标准: C++17 或更高
  • 依赖库: 系统框架(自动链接)

7. 常见问题​

7.1 DLL/dylib 加载失败​

Windows:

  • 确保 webglhost_export.dll 在可执行文件同目录或系统路径中
  • 检查 Visual C++ Redistributable 是否已安装

macOS:

  • 使用绝对路径或相对路径加载 dylib
  • 检查库签名和权限

7.2 初始化失败​

  • 验证 SDK Key 和 Secret
  • 确保运行时文件 runtime/webglhost-runtime.exe(Windows)或 runtime/webglhost-runtime.app(macOS)存在
  • 检查网络连接

7.3 游戏启动失败​

  • 查看错误描述信息

8. 下一步​