c++ 无法嵌入Pdfium -无法解析外部符号

u3r8eeie  于 2023-01-06  发布在  其他
关注(0)|答案(1)|浏览(333)

在按照Google's docs成功构建Pdfium之后,我用VS2022创建了一个新的C控制台应用程序,并尝试嵌入Pdfium构建产生的.lib,但是,它导致了几个未解析的符号,我猜,这些符号应该包含在标准C中。作为一个示例,下面是两个未解析的符号:

fx_string.obj: error LNK2001: unresolved external symbol "void __cdecl std::Cr::__libcpp_verbose_abort(char const *,...)"
fpdf_parser_utility.obj : error LNK2001: unresolved external symbol "public: class std::Cr::basic_ostream<char,struct std::Cr::char_traits<char> > & __cdecl std::Cr::basic_ostream<char,struct std::Cr::char_traits<char> >::write(char const *,__int64)"
    • 采取的步骤**:
  • 使用以下args.gndocs steps之后构建Pdfium:
use_goma = false
is_debug = false
pdf_use_skia = false
pdf_enable_xfa = false
pdf_enable_v8 = false
pdf_is_standalone = false
is_component_build = false
pdf_is_complete_lib = true
  • 创建了一个简单的C++控制台应用程序,包含以下内容(复制自Getting started):
#include <iostream>
#include "../PDFium/public/fpdfview.h"

int main()
{
     std::cout << "PDFium test!\n";

     FPDF_LIBRARY_CONFIG config{};
     config.version = 2;
     config.m_pUserFontPaths = NULL;
     config.m_pIsolate = NULL;
     config.m_v8EmbedderSlot = 0;

     FPDF_InitLibraryWithConfig(&config);

     FPDF_DestroyLibrary();

     return 0;
}
  • 将Pdfium的公共文件夹和生成的.lib文件复制到项目的单独文件夹中,为链接器添加必要字段,并将 C++ 规范设置为stdc++20;下面是.vcxproj
<!-- other tags -->
<ClCompile>
     <!-- other tags -->
     <LanguageStandard>stdcpp20</LanguageStandard>
     <LanguageStandard_C>stdc11</LanguageStandard_C>
</ClCompile>
<!-- other tags -->
<Link>
     <SubSystem>Console</SubSystem>
     <GenerateDebugInformation>true</GenerateDebugInformation>
     <AdditionalLibraryDirectories>$(SolutionDir)PDFium\x64</AdditionalLibraryDirectories>
     <AdditionalDependencies>PDFium.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>

中的相应标记

  • (不成功)测试*
  • 尝试使用和不使用pdf_is_complete_lib = true编译PDFium,因此,也链接单个.obj以及v8xfa支持
  • 尝试使用Microsoft的clang-cl而不是MSBuild(Visual Studio的本机开发包提供的MSBuild)进行编译
  • 尝试使用仓库工具的clang-cl(当前版本为16.0.0)进行编译
  • 尝试了几个选项,发现在这里和那里的SO和互联网上

任何帮助都很感激。先谢了。

lh80um4z

lh80um4z1#

经过几天的失败和(徒劳的)研究,我终于找到了解决办法,张贴在这里供日后参考。

TL;DR;

根据args.gn中设置的标志,Pdfium将需要至少以下内容才能成功构建并启动Getting Started示例:

  • 如果is_component_build = false以及pdf_is_complete_lib = true.obj文件从libc++winmm.lib构建
  • 如果is_component_build = true,并且因此pdf_is_complete_lib = false,所有.dll都是编译得到的,即:
  • absl.dll
  • icuuc.dll
  • x1米11米1x
  • partition_alloc.dll
  • pdfium.dll
  • zlib.dll

也请阅读下面的重要说明,它试图解释这两个标志之间的区别。

详细描述

根据文档,一旦.ninja文件作为gn args <out_dir>的结果生成,就可以看到构建pdfium_unitests.exe需要哪些.obj.lib.dll文件。将这些文件与用于生成pdfium.lib(或pdfium.dll,取决于标志,见下文)的文件进行比较,就可以发现所需的库。
对于is_component_build = falsepdf_is_complete_lib = true

  • 使用ninja -C <out_dir>启动默认编译;这也构建了libc++;
  • 通过ninja -C <out_dir> pdfium生成pdfium.lib(将仅执行链接步骤)
  • (* 可选 *)使用depot tool的lld-link生成libc++.lib,其中包含编译libc++时生成的所有.obj文件:
"C:\path\to\pdfium\third_party\llvm-build\Release+Asserts\bin\lld-link.exe" /lib /OUT:libc++.lib /nologo /WX /ignore:4221 <space-separated list of .obj files in C:\out_dir\obj\buildtools\third_party\libc++\libc++>
  • 链接pdfium.lib、项目中C:\out_dir\obj\buildtools\third_party\libc++\libc++(或上一步中的libc++.lib)和winmm.lib中的所有libc++的.obj文件;例如:
<Link>
    <!-- other options -->
    <AdditionalDependencies>pdfium.lib;libc++.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>

对于is_component_build = truepdf_is_complete_lib = false

  • ninja -C <out_dir> pdfium开始编译;我将编译所有必需的.dll以及.pdb.lib文件,并将它们放在out_dir
  • 在项目中链接pdfium.lib,并在输出目录中复制发出的.dll;假设发出的文件在C:\pdfium\result中,项目的.vcxproj将如下所示:
<!-- ... -->
<Link>
    <AdditionalLibraryDirectories>C:\pdfium\result</AdditionalLibraryDirectories>
    <AdditionalDependencies>pdfium.dll.lib</AdditionalDependencies>
</Link>
<!-- ... -->
<PostBuildEvent>
    <Command>cmd /c "robocopy C:\pdfium\result $(OutDir) /xf *.lib &amp; if %errorlevel% geq 8 exit 0 else exit %errorlevel%"</Command>
</PostBuildEvent>
<!-- ... -->

注解:你需要的文件列在tl中; dr;截面。
注意2:使用robocopy,因为它比xcopy更有效。此外,由于robocopy返回的值,需要检查退出代码

重要提示

pdf_is_complete_libis_component_build将在编译期间分别设置/MT/MD标志。
虽然看起来可能不是问题,但如果两种类型混合,MSBuild将发出警告,因此您需要重新编译Pdfium或通过 * 项目属性〉C/C++〉代码生成〉运行时库 * 更改代码生成方式。
有关详细信息,请参阅Google docs、Microsoft有关flagslinker warning的文档,最终还可参阅this SO question,这些文档可帮助您选择最适合您需要的代码生成。

相关问题