关于为什么windows'.dll不适用于linux的细节

fyo*_*iev 0 c++ linux windows dll shared-libraries

我很好奇能够在Linux编译的C++代码中使用Windows中编译的最原始的DLL库.让我们假设库的问题不是滔天专有的东西从Windows核心;

...只有一个与假的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

除了<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;
}
Run Code Online (Sandbox Code Playgroud)

样本取自惊人的MSDN教程.

所以,让我的问题清楚:是什么阻止linux编译器和链接工具使用无依赖的.dll库MathDuncsDll就像另一个.so?也许,另一个调用语法?或者整个链接过程可能不同?(我想听听细节,而不仅仅是模糊的"这些操作系统在基本上是不同的"和"不可能在一个平台上使用另一个平台上的东西")这些差异需要多少努力才能克服(我假设我们'不使用葡萄酒)?

非常感谢你提前!

Nik*_* C. 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是不可能的.

  • @furikuretsu该代码中没有任何系统调用,但这无关紧要.问题在于其他地方.例如,编译的机器指令如何存储在二进制文件中.Windows无法解析该文件,因此甚至无法加载代码.即使可能,也存在在C++库中找到名称的问题.`cout`例如.在Linux中,它的名称可能与Windows不同.有关说明,请参见http://en.wikipedia.org/wiki/Name_mangling.然后,即使你超越了名称,你仍然必须处理ABI的差异. (2认同)
  • (续)例如,您的MyMathFuncs类的大小在Linux和Windows之间会有所不同,其成员的地址和vtable的布局也会有所不同.因此,对MyMathFuncs :: Add()的调用将导致尝试执行随机数据,就好像它是代码一样. (2认同)