VFP 愛用者社區 首頁 VFP 愛用者社區
本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入

請教DECLARE - DLL

 
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區
上一篇主題 :: 下一篇主題  
發表人 內容
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 名稱、類別名稱(以及你想回傳的型別)跟我說,我可以直接幫你調整成可建置與可呼叫的最小範例。
回頂端
檢視會員個人資料 發送私人訊息
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
無法 在這個版面附加檔案
無法 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作