我继承了一个C++项目,我需要将其转换为DLL,以便在其他项目中使用它。
代码采用 Visual Studio 2010 解决方案构建。我可以编译它并生成 DLL 文件,但没有关联的 lib 文件。我不是Windows开发人员,但似乎我需要导出我想要使用的功能,有两种方法:
第一个选项意味着在我想要导出的每个类或函数前面手动添加 __declspec(ddlexport) 。由于有很多类,并且我无法控制将链接到库的所有应用程序,因此第二个选项(DEF 文件)看起来更有希望。
有没有办法从现有的 DLL 文件生成 DEF 文件?我尝试过不同的解决方案:
使用dumpbin。我没有看到函数名称。就这样:
文件类型:DLL
总结
1000 .data
2000 .idata
18000 .rdata
5000 .reloc
1000 .rsrc
98000 .text
48000 .textbss
仅此而已。我想这意味着我不会出口任何东西。但是,这正是我想做的。我该怎么做?
几年来反复遇到这个问题后,我今天找到了解决方案。这有点 hacky,但实际上可能是使用 Visual Studio 的最佳方法。
因为您不想导出所有可能的符号(特别是因为您的 DLL 本身可能包含大型静态库),并且您无法使用您想要可用的符号编辑文件(对我来说,这是因为它们是第 3 方)必须静态链接才能遵循其使用模式的库),DEF 是最好的解决方案。
如果我们有:
现在构建!
好的,我们收到很多链接器错误......
现在转到“输出”选项卡,请注意输出文本中每个链接器错误行末尾的符号名称:
我们可以创建一个小脚本,其中获取每行的最后一个“单词”,去掉括号,然后将其放入 DEF 文件中。它有效!
就像我说的,这有点hacky(因为你最终只能得到应用程序当时使用的符号)。但实际上,由于您不想导出所有内容,并且您可能需要该库静态链接的库中的符号,因此这可能是解决此问题的最准确方法。
(注意:就我而言,这主要是尝试让插件 DLL 访问应用程序 EXE 中的符号的问题)
为什么不在项目中指定创建 implib 并重新编译。 这里是相关信息。 这将导出所有内容,并且您的其他项目可以链接到 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
....
有关语法的更多信息,请参阅此处。
对于 Visual Studio 2019,这对我有用......
构建两次...第一次没有 DEF 文件。 然后从 VStudio cmd 行窗口运行
DUMPBIN /EXPORTS mydll.dll >myexports.txt
然后使用PHP脚本处理txt并创建DEF文件。
然后仅在 vcxproj 文件中进行这两项更改即可构建第二次...
<ModuleDefinitionFile>$(OutDir)$(TargetName).DEF</ModuleDefinitionFile>
<AdditionalOptions>/IGNORE:4197 %(AdditionalOptions)</AdditionalOptions>
使用 strings64.exe 或 Notepad++ 检查新的 DLL,查看二进制文件并搜索以查看上下文中的字符串。仍然会从嵌入的字符串常量等中找到很多字符串。他们需要注意...如果有人有好的方法,请添加一个链接。