全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1445
推到 Plurk!
推到 Facebook!

DLL返回運算結果的長度問題

答題得分者是:aftcast
h@visli
資深會員


發表:101
回覆:416
積分:418
註冊:2004-02-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-09-24 11:26:36 IP:121.35.xxx.xxx 未訂閱
請先看一下Dll中函數的原型:
function MyEncode(Source: PChar; SourceLen: Integer; var Dest: PChar; DestLen: Integer): Boolean; stdcall;

Host App調用該Dll中的MyEncode函數,傳入Source, 以及SourceLen,Dll運算完成後,通過Dest返回運算的結果,同時在DestLen中指示Dest的長度。

問題:Host App並不知道在調用MyEncode函數時該給Dest多大的內存空間?

我看查看了一些類似Windows API的使用,它是進行兩次調用,第一次調用,取得DestLen的值,再分配Dest空間,然後再次調用同一函數。

但這有一個不好的地方,我的MyEncode函數裡要做大量的計算,這樣如果兩次調用在效率不可取。

所以請教大家有沒有更好的方法?
------
------------------------
博采眾家之長,奉獻綿薄之力
------------------------
RootKit
資深會員


發表:16
回覆:357
積分:419
註冊:2008-01-02

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-09-24 23:41:20 IP:122.126.xxx.xxx 訂閱
不能在DLL 幫它重新申請嗎?或者一開始要大塊一點。就不需要兩次作法。

編輯記錄
RootKit 重新編輯於 2009-09-24 23:46:30, 註解 無‧
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-09-25 19:06:43 IP:210.64.xxx.xxx 訂閱
提供另一個想法…

若dll 是私用,且不會有同時被存取。可於第一次運算好後把buffer放在dll的全域上,然後回傳長度。第二次呼叫時就直接copy上次的buffer。
我想僅copy buffer 速度應該是很快的(相較你所謂的演算法時間很久來說)。
------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
h@visli
資深會員


發表:101
回覆:416
積分:418
註冊:2004-02-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-09-26 09:15:54 IP:218.18.xxx.xxx 未訂閱
1、由DLL申請,這個我也考慮過,但可能會導致內存訪問錯誤。
2、要大塊一點的內存,這個方法就是我現在用的方法,呵呵,這也有個缺陷,就是在實際使用中出現的申請的大小不夠的情況,因為申請多大不好把握。
===================引 用 RootKit 文 章===================
不能在DLL 幫它重新申請嗎?或者一開始要大塊一點。就不需要兩次作法。

------
------------------------
博采眾家之長,奉獻綿薄之力
------------------------
h@visli
資深會員


發表:101
回覆:416
積分:418
註冊:2004-02-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-09-26 09:20:53 IP:218.18.xxx.xxx 未訂閱
您說的這個辦法是個不錯的思路,但我這個DLL也不是私用的。另外在內存管理這塊會比較費勁
===================引 用 aftcast 文 章===================
提供另一個想法…

若dll 是私用,且不會有同時被存取。可於第一次運算好後把buffer放在dll的全域上,然後回傳長度。第二次呼叫時就直接copy上次的buffer。
我想僅copy buffer 速度應該是很快的(相較你所謂的演算法時間很久來說)。
------
------------------------
博采眾家之長,奉獻綿薄之力
------------------------
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-09-26 23:41:30 IP:61.219.xxx.xxx 訂閱
很難一兼二顧,若dll是公用的,那就要使用handle這觀念可能可以達成。即運算完的結果,一樣是存在heap上,但加回傳一個handle做為下次取值的依據,外加長度。第二次呼叫時就以handle、buffer帶入去接值,dll COPY 完buffer後就把heap上的資料清了,也把handle值註消,如此即使multithread的dll也不會出錯。只是記憶管理要花一點點小功夫。

天下沒有白吃的午餐… 時間與複雜度通常反比。若不然就是冒險一次用超級大的(其實也有小技巧可解決,就是把呼叫的參數值限定在一個範圍,然後run一次,就知道max buffer會是多少,當user輸入過大時就不能run,於是就安全了!唯一缺點就是該函式的參數有所受限)。再者就是你所知的連用二次,你也知道windows常幹這樣的事…


------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2009-09-26 23:44:03, 註解 無‧
RootKit
資深會員


發表:16
回覆:357
積分:419
註冊:2008-01-02

發送簡訊給我
#7 引用回覆 回覆 發表時間:2009-10-12 21:25:52 IP:122.126.xxx.xxx 訂閱
最後的補充:

確切的來說,如果要解決這個問題唯一的選項就是交由 DLL 申請內存並傳回指針。
避免由主程式事先需準備一大塊記憶體。
但這裡有很大的問題,當執行主程式釋放由DLL 申請內存位址時,將導致違法操作錯誤。
記得原因是 Delphi 使用 Heap 問題,解決方式:
1. 用其他語言 C or VB ... 撰寫 DLL or 主程式。
2. 由 DLL 申請也由DLL 釋放,也就是說必須在主程式呼叫DLL函數釋放。



系統時間:2017-10-20 13:25:37
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!