  | 
				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 文章: 482
 
  第 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 名稱、類別名稱(以及你想回傳的型別)跟我說,我可以直接幫你調整成可建置與可呼叫的最小範例。 | 
			 
		  | 
	 
	
		| 回頂端 | 
		 | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
  	 
	    
  	   | 
 	
您 無法 在這個版面發表文章 您 無法 在這個版面回覆文章 您 無法 在這個版面編輯文章 您 無法 在這個版面刪除文章 您 無法 在這個版面進行投票 您 無法 在這個版面附加檔案 您 無法 在這個版面下載檔案
  | 
   
  
		 |