本次更新是一次结构性升级,而非可热替换的补丁:头文件入口从单头改为按需 include,命名空间从扁平改为镜像 .NET,字符串 ABI 从宽字符改为 UTF-8;并新增 169 个类名、原生集合 / 嵌套数组 / 字典三种消费形态。旧项目需要修改源码并全量重新编译,不能只替换库文件。
Spire.Pdf for C++ 12.10.7 对比旧版 C++ 包变更明细
源库:
Spire.Pdf.dll12.10.7(netstandard2.0,FileVersion 12.10.7.1420)
适用对象:使用旧版 C++ 包的客户代码 ——#include <Spire.Pdf.o.h>、扁平Spire::Pdf命名空间、wchar_t宽字符接口
对照基准:下称「旧包」= 厂商旧版 C++ 包(src/CPP的形态);「新包」= 本包交付包
| 维度 | 旧包 | 12.10.7 | 变化 |
|---|---|---|---|
| 目标平台 | 3 族(Windows x64 / Linux x64 / macOS) | 10 个 RID(Windows 2 / Linux glibc 2 / musl 2 / OHOS 2 / macOS 2) | 3 → 10;已交付验证仅 win-x64 |
| 包体大小 | —(仓库内无旧包归档) | 75.9 MB(75,894,559 B,win-x64) | — |
.h 文件数 |
675 业务 + 42 common(+ Spire.Pdf.o.h) |
746 业务 + 25 common + pch.h(共 772) |
+71 / −17 / +1 |
class EXPORTS 定义 |
558 | 616(571 个唯一类名) | 新增 169 / 移除 156 |
| C 接口头 | 无 | Spire.Pdf.C.h 6398 条声明 |
新增(内部对接头,非公开 C API) |
| AOT 库版本 | — | 12.10.7.1420 | — |
| 导出符号总数 | — | 6398 | — |
| 内置 boost 头 | 38 | 41 | +3 |
随包示例 .cpp(仓库内) |
—(无旧包示例) | 1 | +1 |
| 文件级差异(业务头基名) | 675 个唯一名 | 686 个唯一名 | +201 / −190 |
类名按基名比对,不含路径;改名(如
PdfFieldActions→PdfFormFieldAdditionalActions)在两侧各计一次。
156 个「移除」里含 5 个旧包用于消歧的前缀名与若干改名接替,不是 156 个能力消失,见 4.7。
兼容性结论
| 维度 | 结论 |
|---|---|
| 源码兼容 | 否 —— 需按第 3、4、6 节改造 |
| 二进制兼容 | 否 —— 必须重新编译并重新链接;只替换 .dll / .lib 去链接旧目标文件会失败 |
| 行为兼容 | 大体一致。类型下溯的失败语义变了(4.4),其余为机械改动 |
一句话:接口形态变了(头文件 / 命名空间 / 字符串 / 少量类名),业务逻辑基本不用动。
需要重新设计的只有三处:Object的下溯写法(含失败语义)、PdfDestination的构造方式、
以及被厂商删除的KeyPressed(见 4.3)。
| 平台族 | 旧包 | 12.10.7 |
|---|---|---|
| Windows | x64(Debug / Release 两档;Spire.Pdf.Cpp.dll / .lib) |
win-x64、win-arm64(SpirePdfCpp.dll / .lib,无 debug 目录) |
| Linux glibc | x64(SpirePdfCpp.so) |
linux-x64、linux-arm64(libSpirePdfCpp.so) |
| Linux musl | — | linux-musl-x64、linux-musl-arm64 |
| OpenHarmony | — | ohos-x86_64、ohos-arm64-v8a |
| macOS | 有(CMake APPLE 分支,.so) |
osx-x64、osx-arm64(.dylib) |
| 图形 / 文本依赖 | Skia(libSkiaSharp) |
Skia + HarfBuzz(libHarfBuzzSharp,新增) |
| 包内容 | 仅 wrapper:AOT 的 Spire.Pdf.Base.dll 与 libSkiaSharp.dll 需自行拷到同目录 |
自带 wrapper + AOT Base + Skia + HarfBuzz |
关键二进制差异:
.lib)。include/ 全量重编,不能只替换库文件。
除命名空间 / 字符串 ABI 变化外,wrapper 公开 API 还跨 DLL 边界传 std::string /
std::vector / std::vector<intrusive_ptr<T>> —— 客户工程与新包的 DLL 必须是同一套 MSVC + STL。新增的部署约束(来自随包 README):
linux-musl-* 与 ohos-* 需要自行部署 ICU(libicuuc.so + libicui18n.so 无版本号副本 + icudt*.dat)
与 fontconfig 链(libfontconfig / freetype / expat / libpng / libz);否则首次构造 PdfDocument
会 FailFast,或 libSkiaSharp.so 装载期失败。.so 的 NEEDED 里(运行期 dlopen 传递依赖),扫 .so 清单看不见,别据此判定「已自包含」。ohos-clang(wrapper 用 std::__n1 libc++ 静态链接,与标准 libc++ 不兼容)。旧版:
include/
Spire.Pdf.o.h # 48 KB 手写总入口,内部 713 条 include
pdf/h/*.h # 675 个扁平业务头
common/h/*.h # 42 个基础类型头
boost/** # 38 个 boost 头
新版:
include/
Spire.Pdf.C.h # 6398 条内部 C 对接声明(非公开 C API)
Spire/Pdf/** # 746 个按 .NET 命名空间分层的业务头
Graphics/ Texts/ Tables/ Actions/ Annotations/ Forms/
Layout/Tables/ Destinations/ Security/ Print/ Utilities/ ...
Spire/Pdf/common/h/** # 25 个基础类型头
Spire/Pdf/pch.h
boost/** # 41 个 boost 头(含 macOS 配置)
Spire.Pdf.o.h 总入口被删除;新版无等价单文件入口,也无聚合伞头、无扁平兼容头。-I:include、include/Spire/Pdf、include/Spire/Pdf/common/h。Spire::Pdf;新版拆成子命名空间,仅 using namespace Spire::Pdf; 不再够用。C2027(使用未定义类型)与 C2065(未声明的标识符)。| 类型 | 旧包 | 新包 |
|---|---|---|
PdfDocument / PdfPageBase / PdfPageSize / FileFormat |
Spire::Pdf::… |
不变(根命名空间) |
PdfCanvas / PdfBrush / PdfFont |
Spire::Pdf::PdfCanvas 等(均在根) |
Spire::Pdf::Graphics::PdfCanvas / …::PdfBrush / …::PdfFont |
PdfGrid |
Spire::Pdf::PdfGrid |
Spire::Pdf::Grid::PdfGrid |
PdfTable(PdfLayoutWidget 派生) |
Spire::Pdf::PdfTable |
Spire::Pdf::Tables::PdfTable |
PdfTextExtractor |
Spire::Pdf::PdfTextExtractor |
Spire::Pdf::Texts::PdfTextExtractor |
PdfBookmark |
Spire::Pdf::PdfBookmark |
Spire::Pdf::Bookmarks::PdfBookmark |
PdfAnnotation |
只有一个 | Annotations::PdfAnnotation 与 Interactive::Annotations::PdfAnnotation |
PdfField |
只有一个 | Fields::PdfField 与 Interactive::Forms::PdfField |
PdfSignature |
只有一个 | Security::PdfSignature 与 Interactive::DigitalSignatures::PdfSignature |
PdfTableElement |
无此类 | Spire::Pdf::Layout::Tables::PdfTableElement(新增) |
让裸名可用:在 namespace Spire::Pdf 内部打开子命名空间(写在外部只能让裸名可见,
限定名 Spire::Pdf::Graphics::… 仍解析不到那层):
#include "Spire/Pdf/PdfDocument.h"
#include "Spire/Pdf/Graphics/PdfCanvas.h"
using namespace Spire::Pdf;
namespace Spire { namespace Pdf {
using namespace ::Spire::Pdf::Graphics; // 让 PdfCanvas、PdfFont 等裸名可用
} }
62 组同名类型(46 类 + 16 枚举)分处两个命名空间(如 Annotations::PdfAnnotation
与 Interactive::Annotations::PdfAnnotation 都是真类型)。每组只能打开一侧,
两侧都打开会让裸名当场二义(C2872);补一条 using X::PdfTable; 也压不过去。
// ❌ 两侧都打开:裸名 PdfTable 当场二义
using namespace ::Spire::Pdf::Tables;
using namespace ::Spire::Pdf::Utilities;
// ✅ 只开一侧;另一侧写全限定名
using namespace ::Spire::Pdf::Tables;
intrusive_ptr<PdfTable> a = /* Tables 版 */;
intrusive_ptr<Spire::Pdf::Utilities::PdfTable> b = /* Utilities 版 */;
// ✅✅ 更推荐:两侧都用命名空间别名,谁也不打开
namespace Tables = ::Spire::Pdf::Tables;
namespace Util = ::Spire::Pdf::Utilities;
intrusive_ptr<Tables::PdfTable> a;
intrusive_ptr<Util::PdfTable> b;
编译报
C2872 'X': ambiguous symbol时就是这一条 —— 按报错位置的类名判断它属于哪一侧。
⚠ 62 组是 12.10.7 实测;换 dll 会改变冲突面本身,不要把它当常量。
LPCWSTR_S 这个名字保留,但定义变了:
typedef const wchar_t* LPCWSTR_S; // 旧包
typedef const char* LPCWSTR_S; // 新包
接口签名随之统一为 const std::string&:
| API | 旧包 | 新包 |
|---|---|---|
PdfDocument::LoadFromFile |
void LoadFromFile(LPCWSTR_S fileName) |
void LoadFromFile(const std::string& fileName) |
PdfDocument::SaveToFile |
void SaveToFile(LPCWSTR_S fileName, FileFormat f) |
void SaveToFile(const std::string& fileName, FileFormat f) |
PdfField::GetFullName |
LPCWSTR_S GetFullName() |
std::string GetFullName() const |
| 旧写法 | 改法 |
|---|---|
L"abc" |
删掉 L → "abc" |
LPCWSTR_S |
可保留(现为 const char*),或改 const char* / std::string |
std::wstring 变量 |
改 std::string,并自行做编码转换(GBK / UTF-16 → UTF-8) |
x.c_str() |
删掉 —— 新接口形参就是 const std::string&,直接传即可 |
⚠
.c_str()是最容易多写的:加了它只是走一遍std::string → const char* → std::string的往返,
编译得过、行为也对,但没必要,还容易让人误以为接口不兼容。
规模参照:旧包头文件里 LPCWSTR_S 出现 1599 处;新包 const std::string& 形参 809 处,
wchar_t 残留 0 处。MSVC 需加 /utf-8;新版头文件含 UTF-8 中文注释。
PdfDestination:可构造基类 → 抽象基类(PdfDestinationMode 一并消失)旧包:PdfDestination 是具体类,先 new 再逐个设属性。
intrusive_ptr<PdfDestination> dest = new PdfDestination(page);
dest->SetMode(PdfDestinationMode::Location); // 旧枚举:Location/FitToPage/FitH/FitR/FitBH
dest->SetLocation(new PointF(0, y));
dest->SetZoom(2.f);
新包:PdfDestination 是抽象基类(protected 构造、零公开成员),
PdfDestinationMode 不存在;能力由 Destinations::PdfExplicitDestinationType(8 值)
与具体子类提供,改为一次性构造:
intrusive_ptr<PdfDestination> dest = new Destinations::PdfXYZExplicitDestination(page, 0, y, 2.f);
| 目的地类型 | 新包类 |
|---|---|
| XYZ | Destinations::PdfXYZExplicitDestination(page, left, top[, zoom]) |
| Fit / FitH / FitV / FitR / FitB / FitBH / FitBV | Destinations::PdfFit*ExplicitDestination(…) |
相应地,
PdfEmbeddedGoToAction的构造形参也从「目的地对象」改成了「页码 + 缩放」(见 4.3)。
KeyPressed)以下为实测的旧 → 新对应(表单 / 注记的动作类在 .NET 侧经过一轮改名,
GetActions() / GetAdditionalActions() 返回的类型尤其容易命中):
| 旧包 | 新包 | 差异 |
|---|---|---|
Spire::Pdf::PdfFieldActions |
Spire::Pdf::Actions::PdfFormFieldAdditionalActions |
成员改名:GetFormat/GetValidate/GetCalculate → GetOnFormat/GetOnValidate/GetOnCalculate(setter 同);鼠标进出上移到基类 PdfAnnotationAdditionalActions(OnEnter/OnExit);KeyPressed 无替代 |
Spire::Pdf::PdfAnnotationActions |
Spire::Pdf::Actions::PdfAnnotationAdditionalActions |
鼠标 / 焦点动作加 On 前缀:GetMouseDown → GetOnMouseDown、GetGotFocus → GetOnReceiveFocus 等;另新增 OnOpenPage/OnClosePage/OnShowPage/OnHidePage;Format/Validate/Calculate 不再在此类 |
Spire::Pdf::PdfDocumentActions |
Spire::Pdf::Actions::PdfDocumentAdditionalActions |
成员改为 GetBeforeClosing/GetBeforeSaving/GetBeforePrinting/GetAfterSaving/GetAfterPrinting(旧 GetBeforeCloseAction 等改为动名词形);GetAfterOpenAction 在新类中无同名成员 |
Spire::Pdf::PdfEmbeddedGoToAction |
Spire::Pdf::Actions::PdfGoToEmbeddedAction |
构造改为 (fileName, pageNumber, zoom);GetIsNewWindow → GetNewWindow、GetFileName → GetEmbeddedFileName(只读) |
Spire::Pdf::PdfTextFind(结果对象) |
Spire::Pdf::Texts::PdfTextFragment |
检索入口改为 new Texts::PdfTextFinder(page)->Find(text);GetBounds/GetPositions/GetSizes 由单值改为 std::vector |
PdfDocument::GetSecurity() |
PdfDocument::GetSecurityPolicy() |
读取改走 GetSecurityPolicy();写入改走 Encrypt(policy)。旧名仍导出但带告警 |
Spire::Pdf::License(类) |
Spire::Pdf::License::LicenseProvider(类) |
License 现在是命名空间;SetLicenseKey/SetLicenseFileName/ClearLicense 仍在,文件路径改 SetLicense(path)、流改 SetLicense(intrusive_ptr<Stream>) |
Spire::Pdf::PdfPaperSizes |
Spire::Pdf::Print::PdfPaperSize |
类改名,但静态常量 A4 等仍不导出(见 6.4) |
Security_PdfSignature / Utilities_PdfTable / Utilities_PdfImageInfo / Collections_PdfCollection / Security_IPdfSignatureFormatter |
Security::PdfSignature / Utilities::PdfTable / Utilities::PdfImageInfo / Collections::PdfCollection / … |
旧包用前缀名消歧;新包改由命名空间区分,裸名不变 |
// 旧包
intrusive_ptr<PdfFieldActions> actions = field->GetActions();
actions->SetFormat(jsAction);
actions->SetKeyPressed(jsAction);
// 新包
intrusive_ptr<Actions::PdfFormFieldAdditionalActions> actions = field->GetActions();
actions->SetOnFormat(jsAction);
// SetKeyPressed:无对应成员
旧包的两个动作类在新 API 里是「基类 + 派生类」关系
(PdfFormFieldAdditionalActions : PdfAnnotationAdditionalActions),成员有交叉,按上表找对应即可。以上是示例而非全集。.NET 侧跨版本的其他改名以编译错误为指引即可(名字不在即改错),
编译器会直接指出是哪个类型/成员。
KeyPressed 无替代:
| API | 旧包 | 新包 | 结论 |
|---|---|---|---|
KeyPressed(表单字段 / 注记的 JS 动作) |
PdfFieldActions::Get/SetKeyPressed、PdfAnnotationActions::Get/SetKeyPressed |
无 | 厂商从 .NET API 删除,无替代,需重新设计该段逻辑 |
在厂商 Demo 套件覆盖到的范围内,其余旧成员都还有对应形态。
Demo 未覆盖的冷门类型可能存在其他 .NET 跨版本差异 —— 以编译错误为准,本文不宣称「除KeyPressed外零缺失」。
Object:类型判定与下溯(含行为变化)| 成员 | 旧包 | 新包 |
|---|---|---|
GetInstanceTypeName() |
public,返回 C++ 修饰名(typeid(T).name()) |
private(调用即 C2248),且内容为托管全名 |
ManagedName() |
不存在 | private(仅生成器内部用) |
CheckType<T>(p) |
public | public,语义不变(true/false) |
Dynamic_cast<T>(p) |
boost 转型,失败时回落到无校验重打标签 ⇒ 永不返回 null | 只做 boost 转型:失败返回 null |
Convert<T>(p) |
无校验重打标签,传错类型也返回非空 | 受检:失败抛 SpireTypeError(带 Actual() / Target()) |
UncheckedCast<T>(p) |
不存在 | 新增的显式逃生舱(仍是无校验重打标签) |
// 旧包:按类型名字符串比较,再无校验强转
if (widget->GetInstanceTypeName() == /* 某个名字 */) { /* … */ }
intrusive_ptr<PdfNewPage> page = Object::Convert<PdfNewPage>(doc->GetPages()->Add()); // 从不失败
// 新包:三种受检写法
if (Object::CheckType<PdfNewPage>(obj)) { /* 只需要 yes/no */ }
if (auto page = Object::Dynamic_cast<PdfNewPage>(obj)) { // 不是该类型 → nullptr
page->DoSomething();
}
try {
auto page = Object::Convert<PdfNewPage>(obj); // 不是该类型 → 抛异常
page->DoSomething();
}
catch (const SpireTypeError& e) {
// e.Actual() = 实际托管全名;e.Target() = 期望全名
}
⚠ 行为变化要点:旧
Convert是「打错标签也当成功」,新Convert会当场抛异常;
旧Dynamic_cast失败会悄悄返回一个「打了新标签」的对象,新Dynamic_cast返回nullptr。
从旧包迁来的代码若依赖「永不为空」,必须补判空或改用Convert+ 异常处理。
| API | 旧包返回 | 新包返回 |
|---|---|---|
PdfField::GetFullName() |
LPCWSTR_S(宽字符) |
std::string(UTF-8) |
Pdf3DAnnotation::Get_3DData() |
intrusive_ptr<Stream> |
std::vector<uint8_t> |
Texts::PdfTextFragment 的 GetBounds/GetPositions/GetSizes |
旧 PdfTextFind 对应 GetBounds/GetPosition/GetSize,均为单值 |
std::vector<intrusive_ptr<…>> |
旧包在 10 个类上导出了 19 个事件的 add_* / remove_* 访问器,例如:
add_PageAdded / remove_PageAdded
add_BeginPageLayout / remove_BeginPageLayout
add_BeginPrint / add_EndPrint
add_QueryRowCount / add_QueryNextRow
add_SaveProgress / add_PaperSettings
新包 C++ Spire/Pdf/** 中这些访问器一个都没有(现测 add_* 仅命中无关的 add_ref)。
但请注意旧包的事件注册本就不完整:16 个 *EventHandler 类里 15 个的 Invoke 是注释掉的
(//virtual void Invoke (…)),客户无法实现回调;只有 BeginRowLayoutEventHandler 有一个
可实现的 virtual void Invoke(...)。因此:
Invoke,但没有注册入口);另外:
*EventArgs / *EventHandler 类本身仍在新包导出面(32 个类名),Invoke 反而生成了;Spire.Pdf.C.h 里有 12 个 _add_ 导出
(如 PdfTable_add_BeginCellLayout、PdfLayoutWidget_add_BeginPageLayout、PdfPageBase_add_BeginSave);Spire.Pdf.C.h 是内部对接头、不是公开 C API ⇒ 依赖事件的 C++ 代码需重新设计,
不能指望「改个类名就能注册」。按类名基名比对,156 个旧类名在新包中不再出现。别把它读成 156 个能力消失:
Security_PdfSignature、Utilities_PdfTable、Utilities_PdfImageInfo、
Collections_PdfCollection、Security_IPdfSignatureFormatter)—— 新包改由命名空间区分,裸名不变;PdfFieldActions、PdfAnnotationActions、PdfEmbeddedGoToAction、
PdfTextFind、PdfDocumentActions、PdfPaperSizes、License 等);| 类别 | 代表类 | 说明 |
|---|---|---|
| 基础值类型 / 集合接口 | Byte、Char、Int16、Int64、Single、UInt16/32/64、DictionaryEntry、ICollection、IDictionary、IDictionaryEnumerator、IList、List、SpireString |
不再需要包装类:字符串用 std::string,整数用原生类型,集合走原生协议,String / Decimal 独立导出 |
| 内部实现 / 序列化 / 格式转换 | ZipArchive*、ZippedContentStream、ZlibZipWriter、XmpMetadata/XmpSchema/XmpStructure(→ PdfXmpMetadata / PdfXmpNamespace)、Story*、FixedDocument/FixedPage/Glyphs、HtmlConverter/HtmlToPdf*、Qt_HtmlConverter、TranslatorFactory |
旧包泄漏的实现类,新包不导出 |
| 绘图 / XPS / WPF 模型(旧包泄漏的 .NET 类型) | Brush、Canvas、Geometry、Path、PathFigure、PathGeometry、MatrixTransform、GradientStop(s)、SolidColorBrush、ImageBrush、Visual、Resources |
不属于 PDF 公共 API,新包不导出 |
| 厂商重构 / 删除的 PDF 类型 | PdfGraphicsState、PdfImageMask、PdfHTMLTextElement、PdfHtmlLayoutFormat、PdfPaperSourceTray、PdfButtonWidgetWidgetItem、PdfTexBoxWidgetItem 等 |
厂商 .NET API 侧已改名 / 删除;以编译错误为准 |
旧包的
PdfPaperSizes里那些常量(Letter/A4…)整段就是注释掉的,两代都没导出过(见 6.4)。
| 功能域 | 代表类 |
|---|---|
| 文档比较 | PdfComparer、PdfCompareOptions |
| 内容构建 / 绘制 | PdfContentBuilder、PdfContentResult、PdfDrawer、PdfAppearances、PdfAppearanceCharacteristics、PdfDefaultAppearance、PdfFreeTextAppearanceBuilder、PdfWatermarkAppearanceBuilder、PdfWatermarkInfo、PdfHatchBrush、PdfIconFit |
| 布局元素(表格 / 图表 / 段落) | PdfTableElement、PdfTable{Cell,Column,Row,Section}Element、PdfLayoutElement、PdfAtomicElement、PdfBlockElement、PdfInlineElement、PdfInlineBlockElement、PdfTextRun、PdfTextWrapElement、PdfImageElement、PdfHeadingElement、PdfListElement/PdfListItemElement、PdfPanel*Element、PdfTocElement、PdfDividerElement、PdfPageTemplate(Set)、PdfParagraphElement、PdfTitleElement |
| 图表元素 | PdfBarChartElement/PdfBarChartStyle、PdfLineChartElement/PdfLineChartStyle、PdfPieChartElement/PdfPieChartStyle、PdfScatterChartElement/PdfScatterChartStyle、PdfStackedBarChartElement/PdfStackedBarChartStyle、PdfHistogramElement/PdfHistogramStyle |
| 条码 | PdfBarcodeElement、PdfBarcodeStyle、PdfInlineBarcode |
| 注记 | PdfCaretAnnotation、PdfCircleAnnotation、PdfFileAttachmentAnnotation、PdfHighlightAnnotation、PdfUnderlineAnnotation、PdfStrikeOutAnnotation、PdfSquigglyAnnotation、PdfSquareAnnotation、PdfPolyAnnotation、PdfPolylineAnnotation、PdfRedactionAnnotation、PdfTextAnnotation、PdfWidgetAnnotation(Collection)、PdfMarkupAnnotation |
| 表单 | PdfChoiceField、PdfChoiceItem(Collection)、PdfPushButtonField、PdfRadioButtonField、PdfTextField、XfaForm + Xfa{Barcode,Button,CheckBox,Choice,ComboBox,DateTime,Image,ListBox,Numeric,RadioButton,Signature,Text}Field |
| 3D / 富媒体 | Pdf3DArtwork、Pdf3DLightingScheme、Pdf3DRenderMode、PdfRichMediaAnnotation、PdfRichMediaAnnotationWidget、PdfRichMediaContent、PdfMovie、PdfMovieAnnotation、PdfScreenAnnotation |
| 安全 / 签名 / 元数据 | PdfSecurityPolicy、PdfPasswordSecurityPolicy、PdfDocumentPrivilege、PdfXmpMetadata、PdfXmpNamespace |
| 转换器 / 导出选项 | PdfToImageConverter、PdfToMarkdownConverter、PdfToSvgConverter、PdfToWordConverter、MarkdownOptions、SvgOptions、PptxOptions、OfdOptions、MetafileOptions、RenderingOptions、IgnoreOptions、ImageCompressionOptions、XlsxSpecialTableLayoutOptions |
| 目的地 | PdfExplicitDestination + PdfXYZExplicitDestination、PdfFitExplicitDestination、PdfFitH/V/R/B/BH/BVExplicitDestination(共 8 个具体子类) |
| 动作 | PdfAnnotationAdditionalActions、PdfDocumentAdditionalActions、PdfFormFieldAdditionalActions、PdfGoToEmbeddedAction、PdfHideAction、PdfResetFormAction、PdfSubmitFormAction、PdfURIAction |
| 字体 / 打印 | PdfFontStore、PdfEmbeddedFontConverter、PdfFontFamilySpec、PdfPaperSize、DefaultPrintLogger、PdfHeaderFooter |
| 文件 / 导入导出 | PdfEmbeddedFile、PdfFileSpecification、PdfFormExportResult、PdfFormImportResult、PdfFixedPrint |
| 基础类型 | String、Decimal、LicenseProvider |
| 其他 | PdfAnchorEntry、PdfAnchorRegistry、PdfNavigationEntry、PdfNavigationRegistry、PdfCollectionItem、PdfImageInfo、PdfNumberFormatter、PdfStandardOptions、PdfThemeProfile、PdfRectangleDifferences、PdfDynamicData、TSAResponse、BitmapOptions |
旧包只能用 GetCount() + GetItem(i)(部分集合连 GetCount 都没有,无法遍历);
新包在保留 GetCount/GetItem 的同时,List<T> 派生集合额外提供原生集合协议:
// 旧包
intrusive_ptr<PdfPageCollection> pages = doc->GetPages();
for (int i = 0; i < pages->GetCount(); ++i) {
intrusive_ptr<PdfPageBase> page = pages->GetItem(i);
}
// 新包(旧写法仍然可用;下面是更地道的写法)
for (intrusive_ptr<PdfPageBase> page : *doc->GetPages()) { /* … */ }
int n = doc->GetPages()->size();
intrusive_ptr<PdfPageBase> first = (*doc->GetPages())[0];
doc->GetPages()->RemoveAt(0); // 集合支持时
⚠ 每次访问都打回同一个托管集合(活对象语义,不是快照)。
⚠ 别用句柄指针相等判断「是否同一元素」—— 每次 getter 都会新建句柄,请比较状态。
交错数组 T[][] 从「不导出」变为 std::vector<std::vector<T>>:
std::vector<std::vector<std::string>> data = {{"a","b","c"}, {"d","e","f"}};
intrusive_ptr<Layout::Tables::PdfTableElement> table = new Layout::Tables::PdfTableElement(3);
table->AddRows(data); // fluent,返回同一个表
std::vector<std::vector<int>> ink = {{1,2,3}, {}}; // 空内层合法
intrusive_ptr<Annotations::PdfInkAnnotation> ann = new Annotations::PdfInkAnnotation(ink);
std::vector<std::vector<int>> back = ann->GetInkList();
字典 Dictionary<K,V> 从「不可枚举句柄 / 不导出」变为原生 std::map<K,V>:
std::map<std::string, std::string> props =
doc->GetDocumentInformation()->GetAllCustomProperties();
// 值按托管真类型建壳,不是裸 Object
std::map<Security::SignInfoType, intrusive_ptr<Object>> fonts;
fonts[Security::SignInfoType::DigitalSigner] = new Common::String("Times New Roman");
sig->SetSignInfoFont(fonts);
null 与空可区分:C++ 侧用配套的
GetX(bool& isNull)/SetX(std::nullptr_t)重载(现测 54 / 54 条,涉及 46 类)。
[Obsolete])API:仍导出,但给编译告警厂商在 .NET 侧标了 [Obsolete] 的成员,新包照常导出(共 72 条声明 / 17 个类),
只在声明前加 SPIRE_DEPRECATED("…厂商原文…"):
/W3(VS 工程默认)能看到,/W1 看不到;-Wdeprecated-declarations。| 类 | 过时成员 | 建议替代 |
|---|---|---|
PdfDocument |
GetSecurity() |
GetSecurityPolicy() + Encrypt(policy) |
PdfDocument |
返回文档式的 MergeFiles(…) 重载 |
static void MergeFiles(inputFiles, outputFile)(自动释放资源) |
PdfViewerPreferences |
SetBookMarkExpandOrCollapse(bool) |
PdfBookmark::SetExpandBookmark(bool) |
PdfUnidimensionalBarcode |
GetEnableCheckDigit() / GetShowCheckDigit() |
无(厂商未给替代) |
PdfSignatureMaker |
12 个 Set{Name,Location,Reason,Date,ContactInfo,DistinguishedName}{,Label} |
PdfSignature / PdfSignatureAppearance 的同名属性 |
PdfTrueTypeFont |
PdfTrueTypeFont(fontFile, size[, style]) 构造 |
PdfTrueTypeFont::FromFontFile(path, size[, style]) |
不建议用
/wd4996或-Wno-deprecated-declarations全局压制 —— 这些告警就是升级路线图。
include/Spire.Pdf.C.h 是新包新增的一种对接形态:6398 条 SPIRE_PDF_API 函数声明,
服务 AOT 原生库与 C++ wrapper 之间的对接。它不是与 DOC 包同款的公开 C API:
int*,字符串为 UTF-8 const char*,末尾 int** 为异常槽;Spire/Pdf/** 的 C++ 头;按顺序扫一遍即可覆盖绝大部分改动:
| # | 搜索 | 改成 | 备注 |
|---|---|---|---|
| 1 | #include <Spire.Pdf.o.h> |
按需 include 具体头(#include "Spire/Pdf/<路径>.h") |
见 3.1 |
| 2 | 编译命令缺 -I |
补 include + include/Spire/Pdf + include/Spire/Pdf/common/h |
见 3.1 |
| 3 | L" |
"(删 L) |
见 4.1 |
| 4 | .c_str() |
直接传 std::string |
删掉,新接口不需要 |
| 5 | LPCWSTR_S |
可保留(现为 const char*) |
若声明了宽字符变量则改 std::string |
| 6 | std::wstring |
std::string |
注意编码转换(UTF-16 / GBK → UTF-8) |
| 7 | GetInstanceTypeName() / ManagedName() |
CheckType<T> / Dynamic_cast<T> / Convert<T> |
两访问器现为 private,见 4.4 |
| 8 | Object::Convert<T> 依赖「永不失败」的写法 |
补判空,或改用 CheckType / Dynamic_cast |
新 Convert 会抛 SpireTypeError |
| 9 | new PdfDestination( |
具体目的地子类构造 | 见 4.2 |
| 10 | PdfDestinationMode |
PdfExplicitDestinationType / 具体子类 |
见 4.2 |
| 11 | PdfFieldActions / PdfAnnotationActions |
Actions::PdfFormFieldAdditionalActions / …AdditionalActions |
见 4.3 |
| 12 | PdfDocumentActions |
Actions::PdfDocumentAdditionalActions |
成员名也变,见 4.3 |
| 13 | PdfEmbeddedGoToAction |
Actions::PdfGoToEmbeddedAction |
构造与属性均变,见 4.3 |
| 14 | PdfTextFind |
Texts::PdfTextFragment + Texts::PdfTextFinder |
检索入口与返回类型均变,见 4.3 / 4.5 |
| 15 | GetKeyPressed / SetKeyPressed |
无替代 | 见 4.3,需重新设计 |
| 16 | License::SetLicenseKey 等 |
License::LicenseProvider::SetLicenseKey 等 |
License 现在是命名空间,见 4.3 |
| 17 | GetSecurity() |
GetSecurityPolicy() + Encrypt(policy) |
旧的仍可用但告警 |
| 18 | add_* / remove_* 事件访问器 |
无 C++ 入口 | 旧包回调大多也不可用(仅行布局事件可注册),见 4.6 |
| 19 | PdfPaperSizes |
Print::PdfPaperSize |
类改名,但 A4 等常量仍不可用,见 6.4 |
| 20 | 裸 byte(vector<byte>) |
unsigned char |
仅 C++17 及以上档需要 |
| 21 | PdfPaperSize::A4 等 |
PdfPageSize::A4() |
两代都没有,非回归 |
| 22 | 编译报 C2872 ambiguous |
按 3.3 写全限定名或命名空间别名 | 62 组同名 |