feat: add native/Java auth SDK, docs, CI, and examples

Made-with: Cursor
This commit is contained in:
hpd840321
2026-04-06 17:42:09 +08:00
commit 3894315759
35 changed files with 4825 additions and 0 deletions
@@ -0,0 +1,11 @@
/*
* 比特安索(Bitanswer)适配器实现(占位)。
*
* 版权所有 © 广州创飞人工智能技术有限公司
* 开发者:huangping@craftlabs.cn
*/
#include "bitanswer_adapter.h"
void bitanswer_adapter_register(void) {
/* 后续里程碑:在此挂接 Bit_LoginEx、Bit_QueryFeature 等与 craftlabs_auth 生命周期对齐。 */
}
+20
View File
@@ -0,0 +1,20 @@
/*
* 比特安索(Bitanswer)适配器注册入口。
*
* 版权所有 © 广州创飞人工智能技术有限公司
* 开发者:huangping@craftlabs.cn
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* 向核心库注册 Bitanswer 相关钩子;当前里程碑可为空实现,后续接入 Bit_LoginEx / Bit_QueryFeature 等。
*/
void bitanswer_adapter_register(void);
#ifdef __cplusplus
}
#endif
+112
View File
@@ -0,0 +1,112 @@
/*
* CraftLabs 授权 SDK — 核心 C API 实现(含桩逻辑与各适配器注册)。
*
* 版权所有 © 广州创飞人工智能技术有限公司
* 开发者:huangping@craftlabs.cn
*/
#include "craftlabs_auth.h"
#include <cstdlib>
#include <cstring>
#include "bitanswer/bitanswer_adapter.h"
#include "selfhosted/selfhosted_adapter.h"
namespace {
/** 不透明句柄对应的内部状态;后续可扩展为供应商特定字段。 */
struct AuthContext {
int dummy;
};
static const AuthResult k_ok = {1, "stub"};
static const AuthResult k_fail = {0, "stub failure"};
AuthContext* as_ctx(AuthHandle h) {
return reinterpret_cast<AuthContext*>(h);
}
void ensure_adapters_registered_once() {
static bool once = false;
if (!once) {
bitanswer_adapter_register();
selfhosted_adapter_register();
once = true;
}
}
} // namespace
extern "C" {
CRAFTLABS_API AuthHandle auth_initialize(const char* /* config_json */) {
ensure_adapters_registered_once();
auto* ctx = new AuthContext{};
ctx->dummy = 1;
return reinterpret_cast<AuthHandle>(ctx);
}
CRAFTLABS_API AuthResult auth_activate(AuthHandle handle, const char* /* license_key */) {
if (!handle) {
return k_fail;
}
(void)as_ctx(handle);
return k_ok;
}
CRAFTLABS_API AuthResult auth_check_license(AuthHandle handle) {
if (!handle) {
return k_fail;
}
return k_ok;
}
CRAFTLABS_API LicenseInfo* auth_get_license_info(AuthHandle handle) {
if (!handle) {
return nullptr;
}
auto* info = static_cast<LicenseInfo*>(std::malloc(sizeof(LicenseInfo)));
if (!info) {
return nullptr;
}
info->is_licensed = 1;
info->expiration_date = 0;
info->feature_names = nullptr;
info->feature_values = nullptr;
info->feature_count = 0;
return info;
}
CRAFTLABS_API void auth_free_license_info(LicenseInfo* info) {
std::free(info);
}
CRAFTLABS_API int32_t auth_has_feature(AuthHandle handle, const char* /* feature_name */) {
if (!handle) {
return 0;
}
return 1;
}
CRAFTLABS_API AuthResult auth_release(AuthHandle handle) {
if (!handle) {
return k_fail;
}
return k_ok;
}
CRAFTLABS_API AuthResult auth_heartbeat(AuthHandle handle) {
if (!handle) {
return k_fail;
}
return k_ok;
}
CRAFTLABS_API void auth_destroy(AuthHandle handle) {
if (!handle) {
return;
}
delete as_ctx(handle);
}
}
+151
View File
@@ -0,0 +1,151 @@
/*
* JNI 桥:java 包 cn.craftlabs.auth.internal.NativeBridge 与 craftlabs_auth.h C API 之间的映射。
*
* 版权所有 © 广州创飞人工智能技术有限公司
* 开发者:huangping@craftlabs.cn
*/
#include <cstdint>
#include <jni.h>
#include "craftlabs_auth.h"
namespace {
AuthHandle from_jlong(jlong ptr) {
return reinterpret_cast<AuthHandle>(static_cast<uintptr_t>(ptr));
}
jobject make_auth_result(JNIEnv* env, const AuthResult& r) {
jclass cls = env->FindClass("cn/craftlabs/auth/AuthResult");
if (!cls) {
return nullptr;
}
jmethodID ctor = env->GetMethodID(cls, "<init>", "(ZLjava/lang/String;)V");
if (!ctor) {
return nullptr;
}
jboolean ok = (r.success != 0) ? JNI_TRUE : JNI_FALSE;
jstring msg = env->NewStringUTF(r.message ? r.message : "");
if (!msg) {
return nullptr;
}
jobject out = env->NewObject(cls, ctor, ok, msg);
env->DeleteLocalRef(msg);
return out;
}
jobject make_license_info(JNIEnv* env, LicenseInfo* info) {
if (!info) {
return nullptr;
}
jclass cls = env->FindClass("cn/craftlabs/auth/LicenseInfo");
if (!cls) {
return nullptr;
}
jmethodID ctor = env->GetMethodID(cls, "<init>", "(ZLjava/util/Date;Ljava/util/Map;)V");
if (!ctor) {
return nullptr;
}
jboolean licensed = info->is_licensed ? JNI_TRUE : JNI_FALSE;
jobject date = nullptr;
if (info->expiration_date != 0) {
jclass dateCls = env->FindClass("java/util/Date");
jmethodID dateCtor = env->GetMethodID(dateCls, "<init>", "(J)V");
jlong ms = static_cast<jlong>(info->expiration_date) * 1000LL;
date = env->NewObject(dateCls, dateCtor, ms);
}
jclass mapCls = env->FindClass("java/util/HashMap");
jmethodID mapCtor = env->GetMethodID(mapCls, "<init>", "()V");
jobject map = env->NewObject(mapCls, mapCtor);
jmethodID put = env->GetMethodID(mapCls, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
for (int i = 0; i < info->feature_count; ++i) {
const char* name = info->feature_names[i];
int v = info->feature_values[i];
jstring jn = env->NewStringUTF(name ? name : "");
jclass boolCls = env->FindClass("java/lang/Boolean");
jmethodID valueOf =
env->GetStaticMethodID(boolCls, "valueOf", "(Z)Ljava/lang/Boolean;");
jobject jb = env->CallStaticObjectMethod(boolCls, valueOf, v ? JNI_TRUE : JNI_FALSE);
env->CallObjectMethod(map, put, jn, jb);
env->DeleteLocalRef(jn);
env->DeleteLocalRef(jb);
}
jobject out = env->NewObject(cls, ctor, licensed, date, map);
if (date) {
env->DeleteLocalRef(date);
}
env->DeleteLocalRef(map);
return out;
}
} // namespace
extern "C" {
JNIEXPORT jlong JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeInitialize(
JNIEnv* env, jclass, jstring configJson) {
const char* utf = configJson ? env->GetStringUTFChars(configJson, nullptr) : nullptr;
AuthHandle h = auth_initialize(utf ? utf : "{}");
if (configJson && utf) {
env->ReleaseStringUTFChars(configJson, utf);
}
return static_cast<jlong>(reinterpret_cast<uintptr_t>(h));
}
JNIEXPORT void JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeDestroy(JNIEnv*,
jclass,
jlong handle) {
auth_destroy(from_jlong(handle));
}
JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeActivate(
JNIEnv* env, jclass, jlong handle, jstring licenseKey) {
const char* utf = licenseKey ? env->GetStringUTFChars(licenseKey, nullptr) : "";
AuthResult r = auth_activate(from_jlong(handle), utf ? utf : "");
if (licenseKey && utf) {
env->ReleaseStringUTFChars(licenseKey, utf);
}
return make_auth_result(env, r);
}
JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeCheckLicense(
JNIEnv* env, jclass, jlong handle) {
AuthResult r = auth_check_license(from_jlong(handle));
return make_auth_result(env, r);
}
JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeGetLicenseInfo(
JNIEnv* env, jclass, jlong handle) {
LicenseInfo* info = auth_get_license_info(from_jlong(handle));
jobject jinfo = make_license_info(env, info);
auth_free_license_info(info);
return jinfo;
}
JNIEXPORT jboolean JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeHasFeature(
JNIEnv* env, jclass, jlong handle, jstring featureName) {
const char* utf = featureName ? env->GetStringUTFChars(featureName, nullptr) : "";
int v = auth_has_feature(from_jlong(handle), utf ? utf : "");
if (featureName && utf) {
env->ReleaseStringUTFChars(featureName, utf);
}
return v ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeRelease(JNIEnv* env,
jclass,
jlong handle) {
AuthResult r = auth_release(from_jlong(handle));
return make_auth_result(env, r);
}
JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeHeartbeat(
JNIEnv* env, jclass, jlong handle) {
AuthResult r = auth_heartbeat(from_jlong(handle));
return make_auth_result(env, r);
}
}
+12
View File
@@ -0,0 +1,12 @@
/*
* 自研适配器 HTTP 客户端桩实现。
*
* 版权所有 © 广州创飞人工智能技术有限公司
* 开发者:huangping@craftlabs.cn
*/
#include "http_client.h"
int selfhosted_http_ping(const char* /* base_url */) {
/* 接入 libcurl 等之后再实现真实请求;当前保证注册阶段可链接通过。 */
return 0;
}
+22
View File
@@ -0,0 +1,22 @@
/*
* 自研适配器用的最小 HTTP 门面(后续可接 libcurl / WinHTTP)。
*
* 版权所有 © 广州创飞人工智能技术有限公司
* 开发者:huangping@craftlabs.cn
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* 对给定基地址做连通性探测;当前为占位实现。
* @param base_url 服务根 URL,可为空(实现定义行为)。
* @return 0 表示占位成功,非 0 预留为错误码。
*/
int selfhosted_http_ping(const char* base_url);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,12 @@
/*
* 自研 HTTP 授权适配器实现。
*
* 版权所有 © 广州创飞人工智能技术有限公司
* 开发者:huangping@craftlabs.cn
*/
#include "selfhosted_adapter.h"
#include "http_client.h"
void selfhosted_adapter_register(void) {
(void)selfhosted_http_ping("");
}
@@ -0,0 +1,18 @@
/*
* 自研 HTTP 授权适配器 — 注册入口。
*
* 版权所有 © 广州创飞人工智能技术有限公司
* 开发者:huangping@craftlabs.cn
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** 注册自研适配器依赖(如 HTTP 客户端探测);可与 Bitanswer 注册并存。 */
void selfhosted_adapter_register(void);
#ifdef __cplusplus
}
#endif