如何快速在QuickJS中实现原生类:Opaque与ClassID的Point类案例精讲

发布时间:2026/10/23 12:12:37

如何快速在QuickJS中实现原生类:Opaque与ClassID的Point类案例精讲 如何快速在QuickJS中实现原生类Opaque与ClassID的Point类案例精讲【免费下载链接】QuickJSQuickJS is a small and embeddable Javascript engine. QuickJS sources are copyright Fabrice Bellard and Charlie Gordon.项目地址: https://gitcode.com/gh_mirrors/quick/QuickJSQuickJS 是一个小巧、可嵌入的 JavaScript 引擎支持用 C 语言扩展原生类。本文以仓库自带的 Point 类为例讲透 Opaque 数据与 ClassID 两大核心机制带你一步步看懂 QuickJS 原生类的完整实现流程。 先搞懂Opaque 与 ClassID 两个核心概念在看代码之前先理解支撑 QuickJS 原生类的两个机制概念作用常用 APIOpaque 数据把 C 结构体挂在 JS 对象上供原生方法读写JS_SetOpaque()/JS_GetOpaque2()ClassID 类标识全局唯一的类编号标识 Opaque 的数据类型并绑定 finalizerJS_NewClassID()/JS_NewClass()一句话总结ClassID 告诉引擎这个对象携带的是哪一类 C 数据Opaque 就是被挂载的 C 数据本身。对象被垃圾回收销毁时引擎会自动调用该类注册的 finalizer 释放内存。官方文档在doc/quickjs.texi的 JS Classes 一节约 L878–L900对此有完整说明。 案例拆解Point 类的 4 步实现示例源码位于examples/point.c它定义了一个二维坐标点类并以原生 ES 模块的形式暴露给 JavaScript。第 1 步定义 C 数据结构与 ClassIDtypedef struct { int x; int y; } JSPointData; static JSClassID js_point_class_id;数据结构只有两个整数ClassID 声明为静态全局变量留给模块初始化时分配examples/point.c第 31–36 行。第 2 步编写构造函数构造函数examples/point.c第 45–75 行只做三件事用js_mallocz()分配JSPointData并把参数解析为 x、y从new_target取prototype调用JS_NewObjectProtoClass()创建对象——这一步是未来 JS 端extends继承能正常工作的关键用JS_SetOpaque()把 C 数据挂到对象上返回该对象。任何一步失败都会走fail分支释放内存并返回JS_EXCEPTIONJS 侧因此能收到正常的异常。第 3 步定义属性与原型方法属性访问x和y使用JS_CGETSET_MAGIC_DEF宏定义 getter/setter第 77–101 行。两个属性共用同一对函数靠 magic 值 0/1 区分——非常省代码的惯用法原型方法norm()方法调用sqrt()计算点到原点的模长实现仅几行。注意所有访问器都先用JS_GetOpaque2()取数据并检查是否为 NULL防止访问未正确构造或已销毁的对象。第 4 步注册类并导出模块js_point_init()第 123–141 行的注册流程是固定四步建议直接记住这个骨架JS_NewClassID(js_point_class_id); // 1. 申请类ID JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, js_point_class); // 2. 注册类定义含 finalizer JS_SetConstructor(ctx, point_class, point_proto); // 3. 关联构造函数与 prototype JS_SetClassProto(ctx, js_point_class_id, point_proto); // 4. 设置类的原型最后用JS_SetModuleExport()把 Point 导出为 ES 模块的导出项模块入口是第 143 行起的js_init_module()。 在 JavaScript 中使用与继承使用示例在examples/test_point.js。对 JS 开发者来说Point用起来和纯 JS 类没有任何区别const pt new Point(2, 3); pt.x 4; // setter 生效 pt.norm(); // 得到 5 class ColorPoint extends Point { ... } // 甚至可以直接继承示例中的ColorPoint第 13–21 行直接extends Point新增了一个color属性。之所以继承能正常工作正是构造函数里用new_target取原型这一步的功劳。 快速上手构建与运行git clone https://gitcode.com/gh_mirrors/quick/QuickJS cd QuickJS make ./qjs examples/test_point.jsMakefile第 158 行已把examples/point.so加入自动构建列表make test测试目标第 398 行也会实际运行这份 Point 示例。⚠️ 新手常见坑与最佳实践忘记检查 Opaque 是否为 NULL对象构造失败或已被回收时JS_GetOpaque2()返回 NULL必须立刻返回JS_EXCEPTION构造函数里忽略new_target写死原型对象会导致 JS 端extends继承断链分清 ClassID 与 JSClass 的作用域ClassID 全局分配所有 runtime 共享而JS_NewClass()需要在每个 JSRuntime 中分别调用失败路径也要释放内存构造函数中途失败要记得js_free()finalizer第 38–43 行里对s可能为 NULL 也做了显式防御值得借鉴。 延伸阅读examples/fib.c、examples/c_module.js更轻量的 C 模块入门示例bjson.c、quickjs-libc.c更大规模的真实原生模块官方文档推荐参考doc/quickjs.texiQuickJS 官方手册涵盖内存管理、异常处理、超时中断等进阶主题。小结QuickJS 原生类的配方很简单OpaqueC 数据 ClassID类型注册 原型方法 四行注册流程。掌握examples/point.c这个骨架后你就可以把任意 C 功能以类的形式优雅地暴露给 JavaScript并天然支持 JS 端的继承与扩展。【免费下载链接】QuickJSQuickJS is a small and embeddable Javascript engine. QuickJS sources are copyright Fabrice Bellard and Charlie Gordon.项目地址: https://gitcode.com/gh_mirrors/quick/QuickJS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/23 12:11:05

跳过L3直奔L4,还是L3是绕不过去的生死坎?:何小鹏激辩杨冬生,全球自动驾驶下半场的责任鸿沟与底盘重构——读2026世界智能网联汽车大会巅峰对话

2026 世界智能网联汽车大会 巅峰对话 | 对话嘉宾:何小鹏(小鹏汽车董事长、CEO)与 杨冬生(比亚迪集团高级副总裁、汽车新技术研究院院长) | 议题:全球自动驾驶如何进入“下半场”?核心洞察&…

2026/10/23 12:11:05

99.9%的对齐够用吗?当AI训练AI,复合偏差正在引爆“对齐退化”危机:递归自举困境、0.1%误差复利与OpenAI正向对齐破局——读OpenAI顶尖研究员Noam Brown与Dwarkesh P

Dwarkesh Podcast 深度技术对谈 | 对话嘉宾:Noam Brown(OpenAI 核心研究员、o1/o3 推理与对齐核心专家)与 Dwarkesh Patel | 核心议题:递归自进化中的对齐退化机制、复合偏差复利与反转路径核心洞察:“最令人担忧的隐患…

2026/10/23 12:11:05

【kali渗透测试】暴力破解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/23 12:11:05

【kali渗透测试】内网横向渗透信息收集基础

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/23 12:06:04

Java进程终止失败?从端口占用到优雅停机的排查与根治

你正在开发一个Java后端服务,改完代码满怀期待地点击“Rerun”,结果开发工具没有像往常一样直接重启,而是弹出一个英文报错:couldnt terminate the existing process for 8080。接下来不管你怎么点停止按钮,界面上的小…

2026/10/22 11:29:28

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/23 0:02:26

Verilog实现FPGA密码锁:矩阵键盘与状态机设计实战

说实话,这几年接触了不少想入门FPGA的朋友,如果你问哪个项目能一口气把Verilog的核心基本功串起来,我通常会推荐电子密码锁。这个项目看着不起眼,却把矩阵键盘扫描、按键消抖、状态机设计、动态显示刷新、外设控制这些数字逻辑里的…

2026/10/23 0:02:26

数据服务监控运维实战:从指标体系到告警治理与故障排查

周末凌晨两点,手机震了。第一反应是“数据服务挂了”。打开电脑看了下,果然,某张核心报表的数据产出时间已经超过SLA两小时,下游三个业务方连着发来问询。这种场景,做过大数据运维的人都不会陌生。数据服务的监控与运维…

2026/10/23 0:02:26

FreeRTOS任务通知实战详解:内核原理、API与避坑指南

裸机编程切到RTOS之后,任务之间的通信和同步永远是躲不开的坎。前面聊过队列、信号量、互斥锁、事件组,这次把FreeRTOS任务通知(Task Notification)单独拎出来讲透。原因很简单:任务通知是FreeRTOS里最容易用错、也最容…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑