 |
VFP 愛用者社區 本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
|
上一篇主題 :: 下一篇主題 |
發表人 |
內容 |
rich
註冊時間: 2025-08-08 文章: 1
第 1 樓
|
發表於: 星期一 八月 11, 2025 4:10 pm 文章主題: 請教DECLARE - DLL |
|
|
敝人設計一個專案 用於將一些PROCEDURE 集成一個專案 再編譯成DLL
用 DECLARE 呼叫時 會產生錯誤 翻譯成中文 應是找不到進入點
以下是我的程式
Define Class WinctDll As Session OlePublic
DataSession=2
c_ctdbf_path=''
Procedure Init
Lparameters tgc_ctdbf_path
This.c_ctdbf_path=tgc_ctdbf_path
Endproc
Procedure Destroy
Clear Class WinctDll
Endproc
Procedure a
LPARAMETERS Parameter1 as string
**
**
endProc
Procedure b
LPARAMETERS Parameter2 as number
endProc
編譯成 WinctDll.dll
使用時
DECLARE a in WinctDll.dll string
a('xxx') 就會錯誤 找不到進入點 請教該如何修改 |
|
回頂端 |
|
 |
小賴
註冊時間: 2004-12-27 文章: 477
第 2 樓
|
發表於: 星期二 八月 12, 2025 12:31 pm 文章主題: |
|
|
DECLARE 一般適用於 作業系統函數庫的調用
以 DEFINE class 的自訂類別函數庫
我都使用 oOBJ = CREATEOBJECT(...) 的方式調用
沒試過 DECLARE
如果 WinctDll.dll 在 LOCAL 端使用可能要先以 REGSVR32 注冊成
COM 元件 (需重關機); VFP 所在電腦 在編譯 DLL 時 應該同時也注冊完了 |
|
回頂端 |
|
 |
CPS0204
註冊時間: 2014-08-24 文章: 480
第 3 樓
|
發表於: 星期二 九月 16, 2025 3:27 pm 文章主題: |
|
|
以下是付費版gpt 回答:
你遇到的是「呼叫方式不對」:
`DECLARE a IN WinctDll.dll` 只適用於「**有明確匯出函式**(exported function)」的原生 DLL(C/C++、stdcall 等)。
而你用 VFP 做的是 **COM/OLE 自動化 DLL**(`OLEPUBLIC` 類別),這種 DLL 不會匯出 `a`、`b` 這類進入點,所以 Windows 會回「找不到進入點」。
解法:把它當 **COM 物件** 來用,不要用 `DECLARE`。
---
# 正確做法(VFP COM DLL)
## 1) 類別寫法(重點:`OLEPUBLIC`、不要在 Destroy 裡 `CLEAR CLASS`)
```foxpro
DEFINE CLASS WinctDll AS Session OLEPUBLIC
DataSession = 2
c_ctdbf_path = ""
FUNCTION Init(tc_ctdbf_path AS String)
THIS.c_ctdbf_path = EVL(tc_ctdbf_path, "")
RETURN .T.
ENDFUNC
* 建議用 FUNCTION,並以 RETURN 回傳值
FUNCTION a(tcParam AS String) AS String
* 這裡寫你的邏輯
RETURN "OK: " + TRANSFORM(tcParam)
ENDFUNC
FUNCTION b(tnParam AS Variant) AS Variant
* 這裡寫你的邏輯
RETURN NVL(tnParam,0) * 2
ENDFUNC
* 不要在 Destroy 裡 CLEAR CLASS,會造成奇怪問題(尤其 COM)
PROCEDURE Destroy
* 做收尾就好
ENDPROC
ENDDEFINE
```
> 備註
>
> * `AS String/Variant` 在 VFP 主要是提示/型別資訊;COM 端最終多半是 VARIANT。
> * 用 `FUNCTION` 比 `PROCEDURE` 更直覺(可 `RETURN`)。`PROCEDURE` 也能回傳,但語意較弱。
## 2) 建置 DLL
* 專案管理員把上面類別加進 PJX。
* 專案 → **Build…** → 選 **DLL**(或 **MTDLL** 若要多執行緒)→ 勾選 *“Register project after build”*(建議)。
* 產生 `WinctDll.dll`。
> 若沒勾自動註冊,可手動註冊:
> `RUN /N REGSVR32 /S FULLPATH("WinctDll.dll")`
## 3) 使用方式(COM Automation)
有兩種常見寫法:
### A. 以 ProgID 建例項(需已註冊)
```foxpro
LOCAL o
o = CREATEOBJECT("WinctDll.WinctDll", "C:\YourPath\") && 第二參數會傳給 Init
? o.a("xxx") && => "OK: xxx"
? o.b(123) && => 246
```
### B. 以 DLL 檔路徑建例項(可省註冊)
```foxpro
LOCAL o
o = NEWOBJECT("WinctDll", "WinctDll.dll", .NULL., "C:\YourPath\")
? o.a("xxx")
? o.b(123)
```
> ProgID 通常是「**專案名.類別名**」。你若專案名與類別名都叫 `WinctDll`,ProgID 就是 `WinctDll.WinctDll`。
---
# 為什麼 `DECLARE … IN` 不行?
* `DECLARE` 會去查 DLL 的 **exports table**,找名為 `a` 的進入點。
* VFP 的 COM DLL 只匯出 `DllGetClassObject` 等 COM 介面用的函式,**不會**匯出你的方法 `a/b`。
* 所以一定「找不到進入點」。
若你真的需要 `DECLARE` 的那種「原生 DLL」呼叫方式,就得用 C/C++ 做出 **FLL/Win32 DLL**,把要呼叫的函式以 `__stdcall` 匯出;這已經不是 VFP 純程式碼能做到的範疇。
---
# 小叮嚀
* 把 `Destroy` 裡的 `CLEAR CLASS WinctDll` 刪掉,避免 COM 物件被釋放時發生類別定義被清掉等副作用。
* 若要回傳錯誤給呼叫端,建議 `ERROR`/`THROW` 或回傳結構化結果(例如物件/JSON 字串),會比 `MESSAGEBOX` 穩定。
* 需要多執行緒請用 `BUILD MTDLL`,並避免使用共用狀態(或自行同步)。
---
需要的話你把 PJX 名稱、類別名稱(以及你想回傳的型別)跟我說,我可以直接幫你調整成可建置與可呼叫的最小範例。 |
|
回頂端 |
|
 |
|
|
您 無法 在這個版面發表文章 您 無法 在這個版面回覆文章 您 無法 在這個版面編輯文章 您 無法 在這個版面刪除文章 您 無法 在這個版面進行投票 您 無法 在這個版面附加檔案 您 無法 在這個版面下載檔案
|
|