【问题标题】:How to generate DLL from existing C++ code using DEF file in Visual Studio 2010如何在 Visual Studio 2010 中使用 DEF 文件从现有 C++ 代码生成 DLL
【发布时间】:2016-02-19 00:58:26
【问题描述】:

我继承了一个 C++ 项目,我需要将其转换为 DLL,以便在其他项目中使用。

代码在 Visual Studio 2010 解决方案中构建。我能够编译它并生成一个 DLL 文件,但没有关联的 lib 文件。我不是windows开发者,但是好像需要导出自己要使用的功能,有两种方式:

第一个选项意味着在我要导出的每个类或函数前面手动添加 __declspec(ddlexport)。由于有很多类,而且我无法控制要链接到库的所有应用程序,因此第二个选项(DEF 文件)看起来更有希望。

有没有办法从现有的 DLL 文件生成 DEF 文件?我尝试了不同的解决方案:

  • 使用expdef。它只是在没有任何信息的情况下崩溃。
  • 使用dumpbin。我没有看到函数名称。就是这样:

    文件类型:DLL

    总结

        1000 .data
        2000 .idata
       18000 .rdata
        5000 .reloc
        1000 .rsrc
       98000 .text
       48000 .textbss
    

仅此而已。我想这意味着我没有出口任何东西。但是,这正是我想要做的。我该怎么做?

【问题讨论】:

  • 也许这可以帮助你:stackoverflow.com/questions/14402415/…
  • 首要任务是避免导出一切。 DLL 的公共接口需要设计,它不是将属性添加到代码中的随机行为。如果您确实有需要导出的 C++ 类,请注意这样做的相当大的危险,那么您非常赞成使用 __declspec(dllexport)。使用 DEF 文件执行此操作是一种残忍且不寻常的惩罚,并且必然会出错。
  • 抱歉我的愚蠢问题。当我声明一个类时,我有一些公共属性和方法。到目前为止,一切都很好。现在,假设我们有 100 个类。每个类都有自己的公共属性和成员。在我(可能是幼稚的)方法中,我只想将代码打包到一个库(一个 DLL 文件)中,并让其他程序只调用每个类的公共接口。那么,如果我使用“public”来定义这个接口,为什么我需要另一种机制来说明哪些部分必须被认为是 public 并且暴露出来才能被调用?

标签: c++ visual-studio-2010 dll dllexport


【解决方案1】:

几年来反复遇到这个问题后,我今天找到了解决方案。这有点 hacky,但实际上它可能是 Visual Studio 的最佳方式。

由于您不想导出所有可能的符号(尤其是因为您的 DLL 本身可能包含大型静态库),并且您无法使用您想要的符号编辑文件(对我来说这是因为它们是必须静态链接以遵循其使用模式的第三方库),而 DEF 是最佳解决方案。

如果我们有:

  • 应用程序 (EXE)
  • 库 (DLL)
  • 库具有 .DEF 文件,这意味着当您构建时,.DEF 中列出的符号将被导出到库 .DLL 并列在 .LIB 文件中。
  • .DEF 文件为空
  • 应用程序链接库的 LIB 文件

现在构建!

好的,我们得到很多链接器错误...

现在转到“输出”选项卡,注意在输出的文本中是每个链接器错误行末尾的符号名称:

我们可以创建一个小脚本,获取每行的最后一个“单词”,去掉括号,然后将其放入您的 DEF 文件中。它有效!

就像我说的那样,这有点 hacky(因为您最终只会得到应用程序当时使用的符号)。但实际上,由于您不想导出所有内容,并且您可能需要该库静态链接的库中的符号,这可能是解决此问题的最准确方法。

(注意:在我的情况下,尝试让插件 DLL 访问应用程序 EXE 中的符号主要是个问题)

【讨论】:

    【解决方案2】:

    为什么不在您的项目中指定创建一个 implib 并重新编译。 Here 是相关信息。 这将导出所有内容,并且您的其他项目可以链接到 implib(一个 .lib 文件)以使用此 dll。另一方面,如果您想避免导出 DLL 中的所有内容,那么您需要创建一个 API(最好是 C,以便与非 Microsoft 编译器兼容,如果这是一种情况),然后仅导出这些函数。这可以通过创建一个小文本文件、将其重命名为 .def 并将其添加到项目中来完成。该文件的格式在 MSDN 中有详细记录,但您需要的最低限度是这样的:

    LIBRARY MyDLLName
    EXPORTS
        function1
        function2
        ....
    

    以上要求在代码中使用函数的确切名称。应将这些函数声明为外部“C”以避免 C++ 名称混淆,并应将 WINAPI 声明为 32 位代码的调用约定。 但是,如果您这样写,您导出的名称可能更“可读”:

    LIBRARY MyDLLName
    EXPORTS
        exportedName1=internalFunctionName1
        exportedName2=internalfunctionName2
        ....
    

    有关语法的更多信息,请参阅here

    【讨论】:

    • 我最近添加了一个项目并编译了..但是现在。当我尝试使用 DEF 文件时,它总是说 LINK : fatal error LNK1104: cannot open file '/DEF:C:\d.def ..
    • 此错误表示“无法打开文件名” - 将您的 .def 文件放在其余源所在的位置并将其添加到项目中。然后在设置中指定要使用 .def 文件。报错的文件名有点奇怪。好像你尝试在命令行中添加它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2013-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多