2009-07-07 74 views
6

我正在使用Delphi爲Ex​​cel創建一個XLL加載項,其中涉及對xlcall32.dll的Excel4v函數進行大量調用。然而,正如我猜測的,很少有德爾菲的專家在這個特定的API上工作過,我希望這個問題也可能在其他API中被觀察到。從Delphi調用特定的Win32 API - 爲什麼例外情況在沒有「asm pop ...」的情況下飛行?

在C中,特別是在附帶的Microsoft Excel 2007 XLL SDK文件xlcall.h,Excel4v定義爲:

int pascal Excel4v(int xlfn, LPXLOPER operRes, int count, LPXLOPER opers[]); 

在Delphi我使用:

function Excel4v(xlfn: Integer; operRes: LPXLOPER; count: Integer; 
    opers: array of LPXLOPER): Integer; stdcall; external 'xlcall32.dll'; 

LPXLOPER是一個指針結構(C)或記錄(德爾福)。

我一直在做關於在Delphi中聲明C函數的作業(this excellent article非常有幫助),我想我正確地聲明瞭Excel4v。然而,從德爾福代碼到功能導致異常調用(「訪問衝突......」是我一直看到)除非他們之後是以下行:

asm pop sink; end; 

其中,「匯」在某處定義作爲整數。

我對彙編沒有任何線索......因此我不會想辦法用「asm pop sink; end;」來修復異常。但是「asm pop sink; end;」確實解決了例外情況。我第一次看到它在this useful article on making XLLs using Delphi中使用。這裏是最相關的報價:。

「從德爾福大絆腳石 與加載項是堆棧上的返回地址後,額外的參數 這都可以免費的每次調用 Excel的我但是隻要你把它扔到 以外,你的加載項就可以正常工作了。添加 行asm pop變量,結束;在 之後每個調用的變量可以是任意的 global,local或對象變量 至少是4個字節長 - 整數是 罰款。重複 - 這一定是包括每個Excel4v調用後的 。否則 你正在構建一個定時炸彈。「

基本上我想了解所發生的情況,以及爲什麼。可能是什麼造成了Win32函數返回一個」關於返回地址後額外的參數棧「又是什麼,實際上意味着什麼呢?

也許會有另一種方式與不同的編譯器選項或聲明函數以不同的方式來解決這個問題,如?

,是有什麼風險有關調用」 asm pop sink;結束;「在每次調用Excel4v之後...?它似乎工作正常,但是,因爲我不明白髮生了什麼事情,所以感覺有點危險......

+0

我正在Delphi中編寫一個XLL,並希望與您取得聯繫。請給我發電子郵件[email protected] – garethm 2011-01-26 23:12:33

回答

8

我不相信它是pascal vs stdcall - 他們是非常相似的調用約定,不應該導致函數退出不匹配的堆棧。

從引用article

這確實是一個非常不錯的 語法,但它是不一樣的 上述數組定義。陣列 - 參數是開放數組參數。 他們可能看起來像任何陣列,他們 確實接受任何陣列,但他們得到一個額外的(隱藏的)參數,其中 數組中的最高索引( 高值)保持 。由於這隻在Delphi中是如此,而不是在C或C++中,所以你會有 有一個真正的問題。 (另請參閱我的 關於開放陣列的文章),因爲 的實際參數數量不會與 匹配。

您正在獲取傳遞給函數的額外「最高數組索引」參數。這是一個int值,必須在函數退出時清理掉,以免發生堆棧損壞和崩潰。文章指出瞭如何將數組傳遞給C函數。

喜歡的東西:

type 
PLPXLOPER = ^LPXLOPER; 

又通PLPXLOPER作爲最後一個參數。

0

你的調用約定是錯誤的,特別是「stdcall」。C聲明指定爲「pascal」

Stdcall按從右到左的順序傳遞參數,期望例程清理並不使用寄存器。 Pascal,OTOH通過參數從左到右的順序。因此,在任何一種情況下,事情都不會像另一半代碼所期望的那樣發生。

改變你的Delphi聲明也是「pascal」而不是「stdcall」。

+0

我試圖指定它爲pascal,但我無法獲得任何調用它然後工作。但是這個函數肯定可以和stdcall一起工作,只要它跟隨着「asm pop ...」這一行。 http://rvelthuis.de/articles/articles-convert.html中的文章提到pascal具有違反直覺的含義,儘管它並不是特定的。 – 2009-07-07 16:25:46

+0

他們曾經是不同的調用約定。現在,「pascal」是一個宏,意味着C標頭中的「stdcall」。 – 2009-07-07 17:40:13

相關問題