首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

在 SpiderMonkey 中建立可呼叫的非函數物件

     編輯:關於C#

前言

在使用 C 語言嵌入 SpiderMonkey JavaScript 引擎時,有時需要建立一個「可被呼叫」的物件,但它並非標準的 Function 物件。例如實作一個 Hash 物件,希望能像 h(key) 這樣直接以函數呼叫語法取得鍵值,而 h 本身是普通物件而非函數。

核心實作:設定 JSClass 的 call 欄位

關鍵在於 JSClass 結構中的 call 欄位。只要將其指向一個符合 JSBool (*)(JSContext*, JSObject*, uintN, jsval*, jsval*) 簽名的 C 函數,該物件在 JS 中即可被呼叫。

static JSBool
call_hash(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    /* 注意:此處的 obj 指向全域物件,而非被呼叫物件本身 */
    *rval = JSVAL_NULL;
    return JS_TRUE;
}

static JSClass hash_class = {
    "Hash", JSCLASS_HAS_PRIVATE,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
    finalize_hash,          /* finalize */
    0,                      /* reserved0 */
    0,                      /* reserved1 */
    call_hash,              /* call — 關鍵在這裡 */
    0, 0, 0, 0, 0           /* 其餘保留 */
};

關鍵難題:如何在 call 回調中取得被呼叫物件 (callee)

官方文件未說明:當引擎呼叫 call_hash 時,參數 obj 是全域物件,並非被呼叫的 Hash 實例。經詢問郵件列表,獲得一個「黑科技」:argv[-2] 即為被呼叫物件本身。

這意味著可在回調中透過 JSObject *callee = JSVAL_TO_OBJECT(argv[-2]); 取得真正的 Hash 物件,進而存取其私有資料。

心得與結語

雖然 SpiderMonkey 功能強大、歷史悠久,但其 C API 設計上存在不少反直覺之處(如上述 argv[-2] 技巧),導致開發體驗不佳。若專案允許,改用 V8、QuickJS 或 Duktape 等現代引擎或許能減少此類坑洞。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved