Skip to Content
Plugin 開發除錯與常見錯誤

除錯與常見錯誤

Plugin 出問題,八成是下面這些。第一個動作永遠一樣:去看 Log。 載入失敗、被拒絕、崩潰、指令名稱撞名,主程式都會記一行; 沒有面板也沒關係,在批次模式下它們會直接印在標準輸出。

先看這三件事

  1. plugin list:你的 Plugin 有沒有被掃到?沒有,往下看「載入類」。
  2. Log(I2C Bus Log 面板,或批次模式的標準輸出):來源是 system 的那些行說明它為什麼被跳過或拒絕。
  3. ver:印出主程式版本與 ABI 版本(例如 nexus_tui 1.0.0.8 (abi 4.1));在 x86 建置上還會說明有沒有例外隔離(SEH isolation)。

載入類:plugin list 看不到我的 Plugin

你在 Log 看到原因怎麼辦
plugin dll skipped: xxx.dll could not be loaded (win32 error 193)架構不符:x86 的 DLL 配 x64 的主程式,或反過來。訊息本身不會說「架構」兩種架構各建一顆,用和主程式相同的那顆,見架構要對:x86/x64
plugin dll skipped: xxx.dll does not export NexusPluginGetInterface進入點沒有匯出,或名字寫錯用範本的 NX_PLUGIN_EXPORT,函式名稱一字不差
plugin dll skipped: xxx.dll returned NULL from NexusPluginGetInterface你的進入點自己回了 NULL,通常是 ABI 主版本不符被你自己拒絕看你的進入點為什麼回 NULL;用 PDK 的 sdk\ 重新編
plugin dll rejected: xxx.dll abi major N (expected 3); ...ABI 主版本不符,訊息會印出雙方的版本與結構大小用與主程式相同 ABI 的 PDK 重新編譯,見版本號與 ABI 相容
plugin dll skipped: xxx.dll crashed inside NexusPluginGetInterface進入點裡崩潰了進入點只該填靜態結構,不要做別的事
plugin rejected: ... slaves == NULL 或 ... slave_decl_size N but this host was built with sizeof(NxSlaveDecl) == M 或 declares N slaves (allowed 1..16)slaves[] 沒填好:沒指定、元素大小沒填 sizeof(NxSlaveDecl)、或個數不在 1~16三個欄位 slaves、slave_count、slave_decl_size 都要填,見第一個 Plugin 1
plugin dll skipped: xxx.dll declares name 'yyy', already registered名稱重複:兩顆 Plugin 用了同一個名字,先註冊的贏改 IcPlugin::name,常見原因是複製範本忘了改名字
什麼訊息都沒有DLL 根本不在被掃描的資料夾(要在主程式旁邊的 plugins\,不是 plugins\子資料夾\)檢查路徑;視窗版可以用選單重新掃描,終端機版重新啟動
註冊被拒絕,cleanup 或名稱是空的name 與 cleanup 是唯二強制的欄位,其餘 callback 才可以是 NULL補上 cleanup(可以是空函式)

掛載類:載進來了,但 plugin switch 出問題

症狀原因怎麼辦
plugin switch: no focused panel; pass @p<N>Plugin 有面板,但沒有指定要放哪一格,也沒有有焦點的面板加 @p0(或其他象限)。Widget/Canvas 型的 Plugin 一律帶 @p<N>
你正在看的那一格顯示 no plugin mounted,而且沒有錯誤訊息掛到了別的面板:沒指定 @p<N> 時 Plugin 會掛到目前有焦點的面板明確指定 @p<N>,見選單:Plugin
面板一直是「沒有 Plugin」你的 Plugin 宣告了 panel_mode = NX_PANEL_MODE_NONE(沒有面板),掛載一律 headless,@p<N> 被忽略想要面板就改成 widget 或 canvas 模式,見架構總覽
掛載後 probe 失敗,面板標題出現 [FAILED]、widget 變灰IC 沒接、位址錯、或 probe() 回了非 ERR_OK;不加 force 時整顆 Plugin 進入失敗狀態保留(不再自動卸載,cleanup 延到重跑或卸載時才呼叫)接好硬體後 plugin restart(Core 偵測到 dongle 離線後又重新連線時會自動重跑一次,輪詢關閉時除外;Core 只在傳輸失敗後才察覺離線,沒有任何東西在讀寫該 dongle 時拔插不一定被察覺,仍需手動 plugin restart;視窗版可點標題列 ↻;重新掛回同一個面板,Log 末尾會寫出要打的指令);沒有硬體時改用 force(plugin restart @p0 force);用 scan 確認位址,見第一個 Plugin 1
面板標題出現 [FAILED](視窗版標題列右端還有一顆 ↻)你的某個 callback 崩潰了,這顆 Plugin 被標記故障並下線(不影響主程式)看 Log 的錯誤行找哪個 callback;修好後 plugin restart 重新掛載,視窗版直接點標題列的 ↻ 也可以(plugin 指令會列出失敗原因)
自訂指令叫不到,Log 有 command 'x' is shadowed by the built-in 'x' command and can never be invoked; rename it指令名稱和內建指令同名(例如 run)改指令名稱;先用 help 看內建指令有哪些

執行類:Plugin 在跑,但行為不對

症狀原因怎麼辦
ExecSync 回 ERR_WRONG_THREAD(-85)在 UI Thread 上呼叫:放進了 init、on_key_press、on_config_save 這類 UI Thread 的 callback硬體存取放在 probe、poll_fn、自訂指令 handler、on_widget_event 這些 Worker 的 callback,見生命週期與執行緒
ERR_HW_OFFLINE(-40)沒接 dongle,或後端開不起來沒有硬體時用 --dongle mock。注意:有實體硬體接著時,視窗版會忽略 --dongle mock,連執行期的 dongle mock 指令也一樣,見第一個 Plugin 1
ExecSync 打到錯的位址你填了自己 slaves[] 裡宣告的位址,而不是 0NxJobRequest 用 memset 清成 0,位址留 0(=這次掛載目前綁定的位址),見讀寫硬體的三種方式
對沒有 bank 的掛載回 ERR_INVALID_PARAMbank 填了非 0沒有 bank 的掛載 bank 只能是 0
ERR_POLL_DISABLED(-61)使用者下了 poll off,你送了低優先級的 SubmitJob這是正確行為,不是錯
面板上的控制項不見了空間不夠被隱藏:OPTIONAL、寬度不夠,或後面的列因面板太矮被隱藏用 nxlayout --solve --w 40 --h 10 之類確認窄面板,把重要的放前面,見Widget 模式深入
LoadLayout 回 ERR_INVALID_PARAM.nxlay 違反版面規則(y 遞減、widget_id 重複、METER/SPIN 沒填 num_max、GROUPBOX 沒填 h、label 超過 31 位元組……)。規則編號與 widget_id 會寫進你的 Plugin 的 Log(WARN),回傳碼只有錯誤類別存檔前先用編輯器的 Error List 或 nxlayout --solve 驗證;在 init 裡檢查回傳值並 LogWrite
LoadLayout 回 ERR_NOT_FOUND/ERR_NOT_SUPPORTEDERR_NOT_FOUND:RCDATA 資源名稱對不上或 .rc 沒編進 DLL(檔案模式則是 .nxlay 沒放在 DLL 旁邊)。ERR_NOT_SUPPORTED:版面含主程式不認得或尚未實作的 type=,整份載入失敗核對資源名稱與 .rc;把 type= 改成這個版本支援的型別
SetWidgetProp 回 ERR_FULL,值沒變label/aux 超過 31 位元組、blob 超過容量,或影子表文字配額(每面板 512 KiB、全體 4 MiB)用盡;舊值保留縮短文字/分批;blob 記錄要補到 4 位元組
載入舊版 Plugin 時 Log 說 abi major 不符以 ABI 3.x 的標頭編出的 DLL(4.0 起 widget 介面整批換掉)。Log 會說明方向:DLL 比主程式舊要「用目前主版本的 PDK 重新編譯」,比主程式新要「更新主程式」用新的 PDK 重新編譯
改了 .nxlay,Plugin 行為完全沒變版面是在載入時才讀的:嵌成 RCDATA 資源的要重新建置 DLL;檔案模式要把新的 .nxlay 複製到 DLL 旁邊。另外若改了 [w.N] 的編號,.h 裡的 WIDGET_ID_* 沒跟著重新產生,.c 就會用舊編號(建置不會替你跑 nxlayout --emit-header,也沒有任何檢查)改完 .nxlay 重新建置(或複製檔案),編號有變就重新 nxlayout --emit-header,見第一個 Plugin 4
改了程式,使用者說「還是舊的」只建了一種架構,或忘了把新 DLL 複製進 plugins\,或主程式還開著沒有重新啟動兩種架構都要重建;複製後關掉主程式重開
on_mouse_event 在 Widget 面板收不到它只送給 Canvas 面板Widget 面板的互動走 on_widget_event
視窗版按鍵沒送到 on_key_press有 widget(文字框等)有鍵盤焦點,按鍵被它吃掉攔的鍵要避開方向鍵、Tab、Space、Enter
on_layout_changed 沒有每次縮放都響只在內容區尺寸真的變了才送正常行為
on_config_save 寫的值沒進 config.ini回傳非 ERR_OK、輸出有不合格的行、超過 4094 位元組、崩潰,或是批次模式逐項檢查見設定持久化
整個主程式被你的 Plugin 帶著崩潰這個建置沒有例外隔離(x86 建置沒有)執行 ver 看有沒有例外隔離;x86 上 Plugin 的崩潰會波及主程式,見架構要對:x86/x64
Canvas Plugin 不畫了,Log 有 plugin render took N ms (limit 10 ms) ... marked faultedui_render_fn 超過 10 ms,被下線且下一幀起不再呼叫見Canvas 模式:用 DrawRegion 一次畫,不要在 render 裡做耗時的事
批次裡 cmd N ('...') failed: unknown command指令名稱不存在,或你的 handler 超過 10 秒見Batch/headless

沒有硬體時的除錯

  • 用模擬後端:nexus_tui.exe --dongle mock(模擬後端預設有兩顆裝置,其中一顆在 0x58)。
  • 視窗版陷阱:有實體硬體接著的時候,視窗版會忽略 --dongle mock。沒有實體硬體時才能穩定用模擬後端。
  • 要臨時測 UI 而不管 probe 結果,掛載時加 force。

還是找不到原因?

  1. 在批次模式重現:nexus_tui.exe --batch --dongle mock --cmd "plugin switch 你的名稱" --cmd "你的指令",全部輸出都在標準輸出,方便存檔比對。
  2. 開啟 Log 的所有等級(--log-level 或視窗版的 Log 等級過濾)。
  3. 在 handler 開頭、結尾與每個錯誤分支用 LogWrite 印出 rc。
  4. 逐支函式的契約查 API 參考(先從 Plugin API 地圖找);規則細節與更多對照表在開發指南,例如常見錯誤對照表。兩份文件也隨 PDK 附在 docs\ 裡。