2012-10-20 21 views
0

我很好奇能夠在Linux編譯的C++代碼中使用Windows中編譯的最原始的DLL庫。假設有問題的庫不是來自Windows核心的可怕的專有;關於爲什麼windows'.dll不適用於linux的具體細節

...只是一個與像假的API(這裏是頭文件和實現):

// MathFuncsDll.h 

namespace MathFuncs 
{ 
    class MyMathFuncs 
    { 
    public: 
     // Returns a + b 
     static __declspec(dllexport) double Add(double a, double b); 

     // Returns a - b 
     static __declspec(dllexport) double Subtract(double a, double b); 
    }; 
} 


// MathFuncsDll.cpp 

#include "MathFuncsDll.h" 

using namespace std; 

namespace MathFuncs 
{ 
    double MyMathFuncs::Add(double a, double b) 
    { 
     return a + b; 
    } 

    double MyMathFuncs::Subtract(double a, double b) 
    { 
     return a - b; 
    } 
} 

該庫將有不超過<的iostream >其他依賴,不是嗎?

的Linux編譯的.cpp將包含以下內容:

// MyExecRefsDll.cpp 
// compile with: /EHsc /link MathFuncsDll.lib 

#include <iostream> 

#include "MathFuncsDll.h" 

using namespace std; 

int main() 
{ 
    double a = 7.4; 
    int b = 99; 

    cout << "a + b = " << 
     MathFuncs::MyMathFuncs::Add(a, b) << endl; 
    cout << "a - b = " << 
     MathFuncs::MyMathFuncs::Subtract(a, b) << endl; 

    return 0; 
} 

Samples were taken from amazing MSDN tutorial.

因此,爲了清楚我的問題:什麼使用dependenceless .DLL庫MathDuncsDll只是停止++編譯和鏈接工具像另一個.so?也許,另一個調用語法?或者,也許整個鏈接過程是不同的? (我想聽聽具體細節,不僅僅是含糊不清的「這些操作系統在本質上是不同的」,「不可能在另一個平臺上使用某些東西」)需要克服這些差異需要多少努力(I假設我們沒有使用Wine)?

非常感謝您提前!

+1

您可能想要谷歌「NdisWrapper」,一個Linux工具,它可以加載實際的Windows驅動程序。這表明你絕對可以從Linux調用Windows代碼,但不容易。 – MSalters

回答

2

不兼容Application Binary Interface是限制用一個工具鏈構建的程序不能在二進制級別與其他工具鏈編譯的程序一起工作的原因。

例如,在C++的Windows中,異常傳播遵循Set Jump/Long Jump模型,而在Linux中則是Dwarf 2.如果您曾經在Windows上使用MinGW作爲工具鏈,TDM-GCC MinGW分佈允許您選擇他們倆。

如果您想使用任何跨平臺項目,您需要使用工具鏈構建它,並且您一直在構建其餘的程序,否則它們不能一起工作。

鏈接的答案包含更多關於此的詳細信息。

+0

謝謝你的回答!與ABI相關的問題包含了bta的說法,這與我所需要的最接近。 – fyodorananiev

+0

不客氣! – vvnraman

5

這應該回答你的問題:https://stackoverflow.com/a/1908981/856199

Windows使用COFF格式,Linux使用ELF。那些不兼容。此外,Windows和Linux具有不同的ABI(請參閱http://en.wikipedia.org/wiki/Application_binary_interface)。這意味着即使加載和執行代碼,也會導致垃圾,因爲與系統其餘部分的通信會被混淆。例如,一個函數會希望它的數據和代碼位於不同的地址並以不同的順序。試圖執行該代碼的結果實際上是隨機的。

當然,Linux編譯器可以使用Windows ABI並生成COFF文件。實際上,它可以,也確實如此;它被稱爲「交叉編譯器」。我正在使用其中的一種在Linux下構建Windows庫和* .exe文件。但是由於COFF與ELF和ABI的差異,使用相同的二進制文件作爲Linux .so和Windows .dll是不可能的。

+0

太棒了!我想知道我的簡單示例所做的系統調用。我不明白操作系統和程序之間的低層交互。你能提供一些閱讀鏈接嗎? – fyodorananiev

+2

@furikuretsu該代碼中沒有任何系統調用,但沒關係。問題在於別處。例如編譯的機器指令如何存儲在二進制文件中。 Windows無法解析該文件,因此甚至無法加載代碼。即使可以,也存在在C++庫中查找名稱的問題。例如,「cout」。在Linux中,這可能與Windows命名不同。請參閱http://en.wikipedia.org/wiki/Name_mangling獲取解釋。然後,即使你忽略了這個名字,你仍然需要處理ABI的差異。 –

+2

(續)例如,MyMathFuncs類的大小在Linux和Windows之間會有所不同,其成員的地址和vtable的佈局也會不同。調用MyMathFuncs :: Add()將導致嘗試執行隨機數據,就像它是代碼一樣。 –

相關問題