Files
TermiNexus 728d090815 feat(vqt6/vipermath/vipersimd/w32/requests): 自绘 Canvas/Graph3D/ChartView 与 Qt6 Charts、新增 gzip 与 torch-lite 模块, 修包装类悬垂指针与中文路径/exp/大文件下载
- vqt6: 包装类统一补 __new__ 堆分配, 修"创建函数栈帧 alloca"被存进字段/跨帧返回后 _ptr 悬垂(传给 QLayout::addWidget 等即崩溃); 菜单类按依赖顺序前移, menuBar()/statusBar() 改返回裸指针; 接入 Qt6 Charts 并新增 _bridge_canvas(Canvas 手绘板 / Graph3D 软件 3D 网络图 / ChartView 折线图); 新增自绘 QRadioButton(圆环+内点, 过渡动画)、剪贴板、应用级字体族 API
- 新增模块: gzip.vp(RFC1952/1951 解码器)、torch/(torch-lite 稠密张量 + conv/pool 前反向)
- vipersimd: 新增 scalar_fma/add/mul/sqrt_array 未向量化对照内核(与对应 SIMD 版逐位一致)
- w32: 新增 UTF-8/UTF-16 路径转换, CreateFile/CreateDirectory 走 W 系列, 修中文路径被按 GBK 误读; read_all 参数 max_count -> buf_size 并文档化"容量含终止符"契约
- requests: https 响应缓冲按需翻倍扩容(上限 256MB), 修 MB 级正文(如 MNIST .gz)被 4KB 静默截断
- vipermath: 重写 exp 为范围归约 + 短泰勒, 修负值发散(x=-30 得 3.7e10)与 NaN 触发 2^31 次缩放导致的卡死
- builtins: 新增 sizet/uzt 别名; stdarg: va_arg 参数 CType -> CPtr
- chore: 删除 vendored jpeg change.log
2026-09-10 23:09:05 +08:00

506 lines
18 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ============================================================
// vqt6/_bridge_core.cpp — QtCore C 桥接层实现
// ============================================================
#include "_bridge.h"
#include <QString>
#include <QByteArray>
#include <QObject>
#include <QCoreApplication>
#include <QGuiApplication>
#include <QClipboard>
#include <QTimer>
#include <QVariant>
#include <QEvent>
#include <QStringList>
#include <QList>
#include <QHash>
#include <QMutex>
#include <QUrl>
#include <cstring>
// ============================================================
// 资源文件标准 URL(QSS url(...) 用)
// ============================================================
extern "C" VQT6_API void vqt6_asset_url_utf8(char* buf, int buf_size, const char* name) {
if (buf == nullptr || buf_size <= 0 || name == nullptr) return;
QString url = QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QStringLiteral("/") + QString::fromUtf8(name)).toString();
QByteArray u = url.toUtf8();
int n = static_cast<int>(u.size());
if (n >= buf_size) n = buf_size - 1;
std::memcpy(buf, u.constData(), static_cast<size_t>(n));
buf[n] = '\0';
}
// 全局回调表(线程安全)
namespace {
QMutex g_slot_mutex;
QHash<int, QPair<vqt6_slot_callback_t, void*>> g_slots;
int g_next_slot_id = 1000; // 避开小整数 slot_id(用户可能直接用 trigger_slot 测试)
}
// ============================================================
// QString
// ============================================================
extern "C" VQT6_API void* vqt6_qstring_create(const char* utf8) {
if (utf8 == nullptr) return nullptr;
return new QString(QString::fromUtf8(utf8));
}
extern "C" VQT6_API size_t vqt6_qstring_to_utf8(void* qstr, char* buf, size_t buf_size) {
if (qstr == nullptr || buf == nullptr || buf_size == 0) return 0;
QString* s = static_cast<QString*>(qstr);
QByteArray ba = s->toUtf8();
size_t len = static_cast<size_t>(ba.size());
if (len >= buf_size) len = buf_size - 1;
std::memcpy(buf, ba.constData(), len);
buf[len] = '\0';
return len;
}
extern "C" VQT6_API void vqt6_qstring_free(void* qstr) {
delete static_cast<QString*>(qstr);
}
extern "C" VQT6_API int vqt6_qstring_length(void* qstr) {
if (qstr == nullptr) return 0;
return static_cast<QString*>(qstr)->length();
}
extern "C" VQT6_API int vqt6_qstring_is_empty(void* qstr) {
if (qstr == nullptr) return 1;
return static_cast<QString*>(qstr)->isEmpty() ? 1 : 0;
}
extern "C" VQT6_API int vqt6_qstring_equals(void* qstr, void* other) {
if (qstr == nullptr || other == nullptr) return 0;
return *static_cast<QString*>(qstr) == *static_cast<QString*>(other) ? 1 : 0;
}
extern "C" VQT6_API void* vqt6_qstring_append(void* qstr, void* other) {
if (qstr == nullptr || other == nullptr) return nullptr;
return new QString(*static_cast<QString*>(qstr) + *static_cast<QString*>(other));
}
// ============================================================
// QByteArray
// ============================================================
extern "C" VQT6_API void* vqt6_qbytearray_create(const void* data, size_t size) {
if (data == nullptr) return new QByteArray();
return new QByteArray(static_cast<const char*>(data), static_cast<int>(size));
}
extern "C" VQT6_API void* vqt6_qbytearray_data(void* qba, size_t* out_size) {
if (qba == nullptr) return nullptr;
QByteArray* ba = static_cast<QByteArray*>(qba);
if (out_size != nullptr) *out_size = static_cast<size_t>(ba->size());
return ba->data();
}
extern "C" VQT6_API size_t vqt6_qbytearray_size(void* qba) {
if (qba == nullptr) return 0;
return static_cast<size_t>(static_cast<QByteArray*>(qba)->size());
}
extern "C" VQT6_API void vqt6_qbytearray_free(void* qba) {
delete static_cast<QByteArray*>(qba);
}
// ============================================================
// QObject
// ============================================================
extern "C" VQT6_API void vqt6_qobject_delete(void* obj) {
if (obj == nullptr) return;
delete static_cast<QObject*>(obj);
}
extern "C" VQT6_API void vqt6_qobject_delete_later(void* obj) {
if (obj == nullptr) return;
static_cast<QObject*>(obj)->deleteLater();
}
extern "C" VQT6_API void vqt6_qobject_set_object_name(void* obj, void* name) {
if (obj == nullptr || name == nullptr) return;
static_cast<QObject*>(obj)->setObjectName(*static_cast<QString*>(name));
}
extern "C" VQT6_API void* vqt6_qobject_object_name(void* obj) {
if (obj == nullptr) return nullptr;
return new QString(static_cast<QObject*>(obj)->objectName());
}
extern "C" VQT6_API void vqt6_qobject_set_parent(void* child, void* parent) {
if (child == nullptr) return;
static_cast<QObject*>(child)->setParent(static_cast<QObject*>(parent));
}
extern "C" VQT6_API void* vqt6_qobject_parent(void* obj) {
if (obj == nullptr) return nullptr;
return static_cast<QObject*>(obj)->parent();
}
extern "C" VQT6_API int vqt6_qobject_connect(void* sender, const char* signal_name,
void* receiver, const char* slot_name) {
if (sender == nullptr || receiver == nullptr || signal_name == nullptr || slot_name == nullptr)
return 0;
return QObject::connect(
static_cast<QObject*>(sender), signal_name,
static_cast<QObject*>(receiver), slot_name
) ? 1 : 0;
}
extern "C" VQT6_API int vqt6_qobject_disconnect(void* sender, const char* signal_name,
void* receiver, const char* slot_name) {
if (sender == nullptr || receiver == nullptr) return 0;
return QObject::disconnect(
static_cast<QObject*>(sender), signal_name,
static_cast<QObject*>(receiver), slot_name
) ? 1 : 0;
}
extern "C" VQT6_API void vqt6_qobject_install_event_filter(void* watched, void* filter) {
if (watched == nullptr || filter == nullptr) return;
static_cast<QObject*>(watched)->installEventFilter(static_cast<QObject*>(filter));
}
extern "C" VQT6_API void vqt6_qobject_remove_event_filter(void* watched, void* filter) {
if (watched == nullptr || filter == nullptr) return;
static_cast<QObject*>(watched)->removeEventFilter(static_cast<QObject*>(filter));
}
// ============================================================
// QCoreApplication
// ============================================================
extern "C" VQT6_API void* vqt6_qcoreapp_create(const char* app_name) {
if (app_name == nullptr) return nullptr;
int argc = 1;
static char app_name_copy[1024];
std::strncpy(app_name_copy, app_name, sizeof(app_name_copy) - 1);
app_name_copy[sizeof(app_name_copy) - 1] = '\0';
char* argv[] = { app_name_copy, nullptr };
return new QCoreApplication(argc, argv);
}
extern "C" VQT6_API void* vqt6_qcoreapp_instance(void) {
return QCoreApplication::instance();
}
extern "C" VQT6_API int vqt6_qcoreapp_exec(void* app) {
if (app == nullptr) return -1;
return static_cast<QCoreApplication*>(app)->exec();
}
extern "C" VQT6_API void vqt6_qcoreapp_quit(void* app, int exit_code) {
if (app == nullptr) return;
// 优先使用 exit_code 重载
QCoreApplication* a = static_cast<QCoreApplication*>(app);
if (a == QCoreApplication::instance()) {
a->exit(exit_code);
}
}
extern "C" VQT6_API void vqt6_qcoreapp_exit(void* app, int exit_code) {
if (app == nullptr) return;
static_cast<QCoreApplication*>(app)->exit(exit_code);
}
extern "C" VQT6_API void vqt6_qcoreapp_process_events(void* app, int flags) {
if (app == nullptr) return;
static_cast<QCoreApplication*>(app)->processEvents(static_cast<QEventLoop::ProcessEventsFlag>(flags));
}
extern "C" VQT6_API void vqt6_qcoreapp_post_event(void* receiver, void* event) {
if (receiver == nullptr || event == nullptr) return;
QCoreApplication::postEvent(static_cast<QObject*>(receiver), static_cast<QEvent*>(event));
}
extern "C" VQT6_API int vqt6_qcoreapp_send_event(void* receiver, void* event) {
if (receiver == nullptr || event == nullptr) return 0;
return QCoreApplication::sendEvent(static_cast<QObject*>(receiver), static_cast<QEvent*>(event)) ? 1 : 0;
}
extern "C" VQT6_API void* vqt6_qcoreapp_organization_name(void* app) {
if (app == nullptr) return nullptr;
return new QString(QCoreApplication::organizationName());
}
extern "C" VQT6_API void vqt6_qcoreapp_set_organization_name(void* app, void* name) {
if (app == nullptr || name == nullptr) return;
QCoreApplication::setOrganizationName(*static_cast<QString*>(name));
}
extern "C" VQT6_API void* vqt6_qcoreapp_application_name(void* app) {
if (app == nullptr) return nullptr;
return new QString(QCoreApplication::applicationName());
}
extern "C" VQT6_API void vqt6_qcoreapp_set_application_name(void* app, void* name) {
if (app == nullptr || name == nullptr) return;
QCoreApplication::setApplicationName(*static_cast<QString*>(name));
}
// ============================================================
// QTimer
// ============================================================
extern "C" VQT6_API void* vqt6_qtimer_create(void) {
return new QTimer();
}
extern "C" VQT6_API void* vqt6_qtimer_create_with_parent(void* parent) {
if (parent == nullptr) return nullptr;
return new QTimer(static_cast<QObject*>(parent));
}
extern "C" VQT6_API void vqt6_qtimer_start(void* timer, int interval_ms) {
if (timer == nullptr) return;
static_cast<QTimer*>(timer)->start(interval_ms);
}
extern "C" VQT6_API void vqt6_qtimer_stop(void* timer) {
if (timer == nullptr) return;
static_cast<QTimer*>(timer)->stop();
}
extern "C" VQT6_API void vqt6_qtimer_set_interval(void* timer, int interval_ms) {
if (timer == nullptr) return;
static_cast<QTimer*>(timer)->setInterval(interval_ms);
}
extern "C" VQT6_API int vqt6_qtimer_interval(void* timer) {
if (timer == nullptr) return 0;
return static_cast<QTimer*>(timer)->interval();
}
extern "C" VQT6_API int vqt6_qtimer_is_active(void* timer) {
if (timer == nullptr) return 0;
return static_cast<QTimer*>(timer)->isActive() ? 1 : 0;
}
extern "C" VQT6_API void vqt6_qtimer_set_single_shot(void* timer, int single_shot) {
if (timer == nullptr) return;
static_cast<QTimer*>(timer)->setSingleShot(single_shot != 0);
}
extern "C" VQT6_API int vqt6_qtimer_is_single_shot(void* timer) {
if (timer == nullptr) return 0;
return static_cast<QTimer*>(timer)->isSingleShot() ? 1 : 0;
}
// ============================================================
// QVariant
// ============================================================
extern "C" VQT6_API void* vqt6_qvariant_create_int(int value) {
return new QVariant(value);
}
extern "C" VQT6_API void* vqt6_qvariant_create_double(double value) {
return new QVariant(value);
}
extern "C" VQT6_API void* vqt6_qvariant_create_bool(int value) {
return new QVariant(value != 0);
}
extern "C" VQT6_API void* vqt6_qvariant_create_string(void* s) {
if (s == nullptr) return new QVariant();
return new QVariant(*static_cast<QString*>(s));
}
extern "C" VQT6_API int vqt6_qvariant_to_int(void* v, int* ok) {
if (v == nullptr) return 0;
bool bok = false;
int val = static_cast<QVariant*>(v)->toInt(&bok);
if (ok != nullptr) *ok = bok ? 1 : 0;
return val;
}
extern "C" VQT6_API double vqt6_qvariant_to_double(void* v, int* ok) {
if (v == nullptr) return 0.0;
bool bok = false;
double val = static_cast<QVariant*>(v)->toDouble(&bok);
if (ok != nullptr) *ok = bok ? 1 : 0;
return val;
}
extern "C" VQT6_API int vqt6_qvariant_to_bool(void* v, int* ok) {
if (v == nullptr) return 0;
bool bok = false;
bool val = static_cast<QVariant*>(v)->toBool();
if (ok != nullptr) *ok = 1;
return val ? 1 : 0;
}
extern "C" VQT6_API void* vqt6_qvariant_to_string(void* v) {
if (v == nullptr) return nullptr;
return new QString(static_cast<QVariant*>(v)->toString());
}
extern "C" VQT6_API int vqt6_qvariant_type_id(void* v) {
if (v == nullptr) return 0;
return static_cast<int>(static_cast<QVariant*>(v)->typeId());
}
extern "C" VQT6_API int vqt6_qvariant_is_valid(void* v) {
if (v == nullptr) return 0;
return static_cast<QVariant*>(v)->isValid() ? 1 : 0;
}
extern "C" VQT6_API void vqt6_qvariant_free(void* v) {
delete static_cast<QVariant*>(v);
}
// ============================================================
// QEvent
// ============================================================
extern "C" VQT6_API int vqt6_qevent_type(void* event) {
if (event == nullptr) return 0;
return static_cast<int>(static_cast<QEvent*>(event)->type());
}
extern "C" VQT6_API void vqt6_qevent_accept(void* event) {
if (event == nullptr) return;
static_cast<QEvent*>(event)->accept();
}
extern "C" VQT6_API void vqt6_qevent_ignore(void* event) {
if (event == nullptr) return;
static_cast<QEvent*>(event)->ignore();
}
extern "C" VQT6_API int vqt6_qevent_is_accepted(void* event) {
if (event == nullptr) return 0;
return static_cast<QEvent*>(event)->isAccepted() ? 1 : 0;
}
// ============================================================
// QStringList
// ============================================================
extern "C" VQT6_API void* vqt6_qstringlist_create(void) {
return new QStringList();
}
extern "C" VQT6_API void vqt6_qstringlist_append(void* list, void* str) {
if (list == nullptr || str == nullptr) return;
static_cast<QStringList*>(list)->append(*static_cast<QString*>(str));
}
extern "C" VQT6_API int vqt6_qstringlist_size(void* list) {
if (list == nullptr) return 0;
return static_cast<QStringList*>(list)->size();
}
extern "C" VQT6_API void* vqt6_qstringlist_at(void* list, int index) {
if (list == nullptr) return nullptr;
QStringList* sl = static_cast<QStringList*>(list);
if (index < 0 || index >= sl->size()) return nullptr;
return new QString(sl->at(index));
}
extern "C" VQT6_API void vqt6_qstringlist_free(void* list) {
delete static_cast<QStringList*>(list);
}
// ============================================================
// QByteArrayList
// ============================================================
extern "C" VQT6_API void* vqt6_qbytearraylist_create(void) {
return new QList<QByteArray>();
}
extern "C" VQT6_API void vqt6_qbytearraylist_append(void* list, void* qba) {
if (list == nullptr || qba == nullptr) return;
static_cast<QList<QByteArray>*>(list)->append(*static_cast<QByteArray*>(qba));
}
extern "C" VQT6_API int vqt6_qbytearraylist_size(void* list) {
if (list == nullptr) return 0;
return static_cast<QList<QByteArray>*>(list)->size();
}
extern "C" VQT6_API void* vqt6_qbytearraylist_at(void* list, int index) {
if (list == nullptr) return nullptr;
QList<QByteArray>* qbl = static_cast<QList<QByteArray>*>(list);
if (index < 0 || index >= qbl->size()) return nullptr;
return new QByteArray(qbl->at(index));
}
extern "C" VQT6_API void vqt6_qbytearraylist_free(void* list) {
delete static_cast<QList<QByteArray>*>(list);
}
// ============================================================
// 全局回调注册表
// ============================================================
extern "C" VQT6_API void vqt6_register_slot(int slot_id, void* user_data) {
QMutexLocker locker(&g_slot_mutex);
g_slots.insert(slot_id, QPair<vqt6_slot_callback_t, void*>(nullptr, user_data));
}
extern "C" VQT6_API void vqt6_unregister_slot(int slot_id) {
QMutexLocker locker(&g_slot_mutex);
g_slots.remove(slot_id);
}
extern "C" VQT6_API void vqt6_trigger_slot(int slot_id) {
// 拷贝条目后释放锁再回调,避免回调内再触发/注册时对非递归 QMutex 死锁
QPair<vqt6_slot_callback_t, void*> entry(nullptr, nullptr);
{
QMutexLocker locker(&g_slot_mutex);
auto it = g_slots.find(slot_id);
if (it == g_slots.end()) return;
entry = it.value();
}
if (entry.first != nullptr) {
entry.first(slot_id, entry.second);
}
}
extern "C" VQT6_API int vqt6_signal_register(vqt6_slot_callback_t cb, void* user_data) {
if (cb == nullptr) return -1;
QMutexLocker locker(&g_slot_mutex);
int id = ++g_next_slot_id;
g_slots.insert(id, QPair<vqt6_slot_callback_t, void*>(cb, user_data));
return id;
}
extern "C" VQT6_API void vqt6_signal_unregister(int slot_id) {
vqt6_unregister_slot(slot_id);
}
// ============================================================
// QTimer — timeout 信号 → 回调
// ============================================================
extern "C" VQT6_API void vqt6_qtimer_connect_timeout(void* timer, vqt6_slot_callback_t cb, void* user_data) {
if (timer == nullptr) return;
int slot_id = vqt6_signal_register(cb, user_data);
if (slot_id < 0) return;
QObject::connect(static_cast<QTimer*>(timer), &QTimer::timeout,
static_cast<QTimer*>(timer), [slot_id]() {
vqt6_trigger_slot(slot_id);
});
}
// ============================================================
// 剪贴板
// ============================================================
extern "C" VQT6_API void vqt6_clipboard_set_text_utf8(const char* utf8) {
QClipboard* cb = QGuiApplication::clipboard();
if (cb == nullptr || utf8 == nullptr) return;
cb->setText(QString::fromUtf8(utf8));
}
extern "C" VQT6_API int vqt6_clipboard_text_utf8(char* buf, int buf_size) {
if (buf == nullptr || buf_size <= 0) return 0;
QClipboard* cb = QGuiApplication::clipboard();
if (cb == nullptr) {
buf[0] = '\0';
return 0;
}
QByteArray u = cb->text().toUtf8();
int n = static_cast<int>(u.size());
if (n > buf_size - 1) n = buf_size - 1;
std::memcpy(buf, u.constData(), static_cast<size_t>(n));
buf[n] = '\0';
return n;
}