2009-06-27 72 views
6

什麼是設計的DLL一個C API與傳遞「對象」,這是C運行時依賴的問題,涉及的最佳方式(FILE * malloc返回指針,等...) 。例如,如果兩個DLL與不同版本的運行時間鏈接,我的理解是,您不能安全地將FILE *從一個DLL傳遞到另一個DLL。C運行時的對象,DLL邊界

是唯一的解決方案使用Windows相關的API(這是保證在DLL工作)? C API已經存在並且已經很成熟,但是主要是從unix設計的(當然,仍然需要在unix上工作)。

回答

0

問題與不同的運行時間,因爲FILE *結構屬於 一個運行在Windows系統上是不可解。

但是,如果你寫一個小包裝界面你做了,它並沒有真正傷害。

stdcall IFile* IFileFactory(const char* filename, const char* mode); 

class IFile { 

    virtual fwrite(...) = 0; 
    virtual fread(...) = 0; 

    virtual delete() = 0; 
} 

這是保存在各地的dll邊界通過,並沒有真正傷害。

P.S .:小心如果你開始在dll邊界上拋出異常。如果你在Windows操作系統上實現了一些設計方法,但是在其他方面會失敗,這將很安靜。

1

無論是現有的答案是正確的:由於在Windows下:你有兩個DLL,每一個靜態兩種不同版本的C/C++標準庫的鏈接。

在這種情況下,不應該將指針傳遞到由C/C++標準庫在一個DLL創建到其他結構。原因在於這兩個C/C++標準庫實現之間的結構可能不同。

你不應該做的另一件事是免費從在其他分配的一個DLL通過新的或的malloc分配的指針。堆管理器也可以不同地實施。

請注意,您可以使用DLL之間的指針 - 它們只是指向內存。這是免費的問題。

現在,你可能會發現這個工作,但如果是這樣,那麼你只是運氣。這可能會在未來導致您的問題。您的問題

一個潛在的解決方案是動態鏈接到CRT。例如,您可以動態鏈接到MSVCRT.DLL。這樣你的DLL將總是使用相同的CRT。

請注意,我不建議在DLL之間傳遞CRT數據結構。你可能想看看你是否可以更好地考慮事情。

請注意,我不是Linux/Unix專家 - 但您在這些操作系統上也會遇到同樣的問題。

+0

我明白這個問題 - 我要求的是這個問題的答案:)我希望有一個解決方案,它不會假設改變現有的C API(在簽名中有FILE *等),但似乎沒有如果我不能保證所有的東西都能夠鏈接到相同的C運行時? 儘管在Unix上這個問題在理論上是相同的,但它很少是一個問題,因爲只有一個C運行時。我從來沒有在文件庫之間傳遞FILE *,unix文件描述符的問題 - 很多C APIS都是這樣設計的,並且在這些OS上完美地工作。 – 2009-06-27 16:45:36

0

如果C API存在並且已經成熟,那麼使用純粹的Win32 API API在內部繞過CRT會讓你感覺一半。另一半是確保DLL的用戶使用相應的Win32 API函數。這會使您的API在使用和文檔中的可移植性降低。另外,即使你用這種內存分配方式,CRT函數和Win32函數都處理void *,你仍然遇到文件問題 - Win32 API使用句柄,並且對FILE結構一無所知。

我不太清楚FILE *的侷限性,但我認爲問題與跨模塊的CRT分配相同。 MSVCRT在內部使用Win32來處理文件操作,並且可以從同一進程中的每個模塊使用基礎文件句柄。可能不起作用的是關閉由另一個模塊打開的文件,這涉及在可能不同的CRT上釋放FILE結構。

我會做什麼,如果更改API仍然是一個選項,導出清除功能的任何可能的「對象」在DLL中創建。這些清理函數將以與在該DLL中創建的方式相對應的方式來處理給定對象的處置。這也將使DLL在使用方面絕對便攜。您唯一擔心的就是確保DLL的用戶確實使用清理函數而不是常規的CRT函數。這可以使用幾個技巧,這值得另一個問題...

2

你問一個C,而不是C++解決方案。

在C做這種事情通常的方法(S)是:

  • 設計模塊API根本就沒有需要CRT對象。獲取通過原始C類型傳遞的東西 - 即讓消費者加載文件並簡單地向您傳遞指針。或者,讓消費者傳遞一個完全合格的文件名,在內部打開,閱讀和關閉。

  • 其他c模塊,MS機櫃SD和部分OpenSSL庫iirc使用了一種方法,讓消費應用程序將指向函數的指針傳遞給初始化函數。因此,任何傳遞FILE *的API都會在初始化期間取得一個指向結構的指針,這個結構的函數指針匹配fread,fopen等特徵符。當處理外部FILE *時,DLL總是使用傳入的功能而不是CRT功能。

通過一些簡單的技巧這樣你可以讓你的C DLL的接口完全獨立於主機CRT的 - 或者事實上要求將用C或C++在所有的主機。