为较低版本的 Visual Studio 构建 .dll

Posted

技术标签:

【中文标题】为较低版本的 Visual Studio 构建 .dll【英文标题】:Building .dll for lower version of visual studio 【发布时间】:2011-06-07 05:43:16 【问题描述】:

我正在使用 Visual Studio 2010 构建我的 DLL 库。

而且,其他使用 Visual Studio 2005 的程序员想要使用我的 DLL 库。他可以使用我的 dll 进行编译,但是,在运行他的应用程序时,它会因 bad_alloc 异常而崩溃。我认为这是因为 CRT 版本不同。

在构建我的 DLL 库时,我尝试了 CRT(/MD) 的动态链接和 CRT(/MT) 的静态链接,但都失败了。

那么,我不能制作低版本的Visual Studio可以使用的DLL库吗?如果没有,我该怎么做?

【问题讨论】:

我可以看看你的dll函数原型吗? 其实就是定义为类。 class MF_API my_class ; 其中MF_API 是相应定义的。 【参考方案1】:

据我所知,您只能使用原始类型的 dll 接口。这是因为即使在同一个编译器中,仅通过更改编译标志来更改内存布局,想想通过更改编译器会发生什么。这可能会导致大规模的不确定行为。

并为您的函数接口使用以下格式:

extern "C" __declspec(dllexport) void doSomething(int input);

【讨论】:

【参考方案2】:

您只能导出没有数据成员的抽象基类(至少包含一个纯虚函数)以实现二进制兼容性,我想这就是关于您的 dll 原型问题的原因。这里http://chadaustin.me/cppinterface.html 很好地讨论了这个问题。

【讨论】:

【参考方案3】:

最简单的解决方案:给其他程序员你的DLL的源代码,让他自己编译DLL对旧的CRT。如果这不合适(因为您不想将源代码交给您,或者您的 DLL 无法使用 VC++ 2005 编译),那么您必须获得一个 VC++ 2005 编译器,或者另一个 VC++ 2010。

【讨论】:

这将消除对 dll 的所有使用,例如动态程序更新。而减少编译时间则远没有那么重要。 @Gajet:我假设他只是想将 DLL 提供给另一个以供重用。请不要仅仅因为您不喜欢正确答案而对正确答案投反对票(或者告诉我这里有什么不正确的地方)。 我刚刚评论了为什么投反对票!我的意思是,如果唯一的情况是传输一些代码,给出代码本身是第一件事。一定是dll的优势让他想到了!\【参考方案4】:

如果您的机器上安装了 VS2005,您可以使用 VS2010 新的Platform Toolset 功能来使用 VS2005 编译器。

它位于Project Properties->General->Platform Toolset。 VS100 是 vs2010,VS90 是 2008 年,(我认为)VS80 是你需要的(2005 年......)。

AFAIK,尝试使用不同的工具集构建的 DLL 会更难(尽管可能,因为你没有链接它)。

干杯

【讨论】:

正是我正在寻找的选项【参考方案5】:

最有可能的是,您使用的东西(如 C++ 容器或类型)在 VC++ 编译器实现版本之间发生了变化,并且在使用不同 VC++ 版本构建的 DLL 之间跨 DLL 边界传递这些内容可能会失败。

您需要使用该特定编译器(VS2005 的 VC++ 8.0、2008 的 VC++ 9.0、2010 的 VC++ 10.0...)构建 DLL,以便其他程序员使用它。否则,他必须升级他的 Visual Studio 才能使用与您相同的版本。

【讨论】:

@wallyk - 它与模板无关。 API 随编译器版本而变化。使用 6 年以上的旧版本会限制您的选择。【参考方案6】:

这是一个相当古老的问题,这也是 COM 的原因之一。我建议您执行以下操作 -

    创建一个抽象基类和(也称为接口)(例如 IExportedFunctionality),它公开您当前导出的类(例如 CExportedClass)提供的方法并具有虚拟析构函数。 不要再导出 CExportedClass。 从 IExportedFunctionality 派生 CExportedClass 并确保实现所有方法。

    从名为

    的 Dll 中导出 2 个函数
    a. GetExportedClass which returns a pointer to a new instance of CExportedClass upcast to IExportedFunctionality*.
    b. FreeExportedClass which accepts a IExportedFunctionality* and deletes it.
    

现在您需要做的就是提供带有 IExportedFunctionality 声明的头文件。您甚至可以取消 lib 文件,因为您的用户可以使用 LoadLibrary 和 GetProcAddress 来调用 GetExportedClass 和 FreeExportedClass。

注意:IExportedFunctionality 应该有

    仅纯虚函数 - 因为 IExportedFunctionality 是一个接口而不是实现。 纯虚拟析构函数 - 因此对 IExportedFunctionality* 执行删除操作将转换为对 CExportedClass 析构函数的调用 在 IExportedFunctionality 中没有任何数据成员(正如 user383522 指出的那样,类的二进制布局可能因编译器和不同的字节对齐方式而异)

【讨论】:

以上是关于为较低版本的 Visual Studio 构建 .dll的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Alteryx .yxzp 文件解包为较低版本

为啥 Visual Studio 2010 (msbuild?) 构建速度不快?

在 Visual Studio 中增加构建版本号

在 TFS 构建配置上缺少 Visual Studio 的最新版本 2019 [重复]

从一个 Visual Studio 项目构建多个版本的静态库

Visual Studio Online自动构建版本号增量和装配修补