This update is a structural upgrade, not a hot-swappable patch: the header entry point changes from a single header to on-demand includes, the namespace layout changes from flat to mirroring .NET, and the string ABI changes from wide characters to UTF-8. It also adds 169 class names and three consumption forms — native collections, nested arrays, and dictionaries. Existing projects must modify source and fully recompile; replacing library files alone will not work.
Spire.Pdf for C++ 12.10.7 — Detailed Changes vs. the Old C++ Package
Source library:
Spire.Pdf.dll12.10.7 (netstandard2.0,FileVersion 12.10.7.1420)
Intended audience: customer code using the old C++ package —#include <Spire.Pdf.o.h>, flatSpire::Pdfnamespace,wchar_tstring interfaces
Baseline: "old package" below = the vendor's previous C++ package (the shape ofsrc/CPP); "new package" = the package delivered here
| Dimension | Old package | 12.10.7 | Change |
|---|---|---|---|
| Target platforms | 3 families (Windows x64 / Linux x64 / macOS) | 10 RIDs (Windows 2 / Linux glibc 2 / musl 2 / OHOS 2 / macOS 2) | 3 → 10; only win-x64 is delivered and verified |
| Package size | — (no archived old package in the repo) | 75.9 MB (75,894,559 B, win-x64) | — |
Number of .h files |
675 business + 42 common (+ Spire.Pdf.o.h) |
746 business + 25 common + pch.h (772 total) |
+71 / −17 / +1 |
class EXPORTS definitions |
558 | 616 (571 unique class names) | +169 added / −156 removed |
| C interface header | None | Spire.Pdf.C.h, 6398 declarations |
New (internal interop header, not a public C API) |
| AOT library version | — | 12.10.7.1420 | — |
| Total exported symbols | — | 6398 | — |
| Bundled boost headers | 38 | 41 | +3 |
Bundled sample .cpp (in repo) |
— (no old sample) | 1 | +1 |
| File-level diff (business header base names) | 675 unique names | 686 unique names | +201 / −190 |
Class names are compared by base name, ignoring paths; a rename (e.g.
PdfFieldActions→PdfFormFieldAdditionalActions) counts once on each side.
The 156 "removed" entries include 5 disambiguation prefix names from the old package and several rename replacements — this is not 156 capabilities disappearing; see 4.7.
Compatibility verdict
| Dimension | Verdict |
|---|---|
| Source compatibility | No — migration required per sections 3, 4, 6 |
| Binary compatibility | No — you must recompile and relink; linking old object files against only the replaced .dll / .lib will fail |
| Behavioral compatibility | Largely the same. The failure semantics of type downcasting changed (4.4); everything else is mechanical |
In one sentence: the interface shape changed (headers / namespaces / strings / a few class names), but business logic mostly needs no change.
Only three things need redesign: howObjectdowncasts (including failure semantics), howPdfDestinationis constructed,
and the vendor-deletedKeyPressed(see 4.3).
| Platform family | Old package | 12.10.7 |
|---|---|---|
| Windows | x64 (Debug / Release builds; Spire.Pdf.Cpp.dll / .lib) |
win-x64, win-arm64 (SpirePdfCpp.dll / .lib, no debug directory) |
| 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 | Yes (CMake APPLE branch, .so) |
osx-x64, osx-arm64 (.dylib) |
| Graphics / text dependencies | Skia (libSkiaSharp) |
Skia + HarfBuzz (libHarfBuzzSharp, new) |
| Package contents | Wrapper only: the AOT Spire.Pdf.Base.dll and libSkiaSharp.dll had to be copied into the same directory manually |
Bundles wrapper + AOT Base + Skia + HarfBuzz |
Key binary differences:
.lib).include/; replacing library files alone is not enough.
Beyond the namespace / string ABI changes, the wrapper's public API also passes std::string /
std::vector / std::vector<intrusive_ptr<T>> across the DLL boundary — the customer project and the new package's DLLs must use the same MSVC + STL.New deployment constraints (from the bundled README):
linux-musl-* and ohos-* require you to deploy ICU (libicuuc.so + libicui18n.so copies without version numbers + icudt*.dat)
and the fontconfig chain (libfontconfig / freetype / expat / libpng / libz) yourself; otherwise the first PdfDocument construction
FailFasts, or libSkiaSharp.so fails at load time..so NEEDED entry (they are run-time dlopen transitive dependencies); scanning the .so list will not show them, so do not conclude "self-contained" from that.ohos-clang (the wrapper statically links std::__n1 libc++, which is incompatible with the standard libc++).Old version:
include/
Spire.Pdf.o.h # 48 KB hand-written umbrella entry, 713 includes inside
pdf/h/*.h # 675 flat business headers
common/h/*.h # 42 base type headers
boost/** # 38 boost headers
New version:
include/
Spire.Pdf.C.h # 6398 internal C interop declarations (not a public C API)
Spire/Pdf/** # 746 business headers layered by .NET namespace
Graphics/ Texts/ Tables/ Actions/ Annotations/ Forms/
Layout/Tables/ Destinations/ Security/ Print/ Utilities/ ...
Spire/Pdf/common/h/** # 25 base type headers
Spire/Pdf/pch.h
boost/** # 41 boost headers (including macOS configuration)
Spire.Pdf.o.h umbrella entry is removed; the new version has no equivalent single-file entry, and no aggregating umbrella header, no flat compatibility header.-I flags as described in the README: include, include/Spire/Pdf, include/Spire/Pdf/common/h.Spire::Pdf; the new version splits them into sub-namespaces, so using namespace Spire::Pdf; alone is no longer enough.C2027 (use of undefined type) and C2065 (undeclared identifier).| Type | Old package | New package |
|---|---|---|
PdfDocument / PdfPageBase / PdfPageSize / FileFormat |
Spire::Pdf::… |
Unchanged (root namespace) |
PdfCanvas / PdfBrush / PdfFont |
Spire::Pdf::PdfCanvas etc. (all in the root) |
Spire::Pdf::Graphics::PdfCanvas / …::PdfBrush / …::PdfFont |
PdfGrid |
Spire::Pdf::PdfGrid |
Spire::Pdf::Grid::PdfGrid |
PdfTable (derived from 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 |
Only one | Annotations::PdfAnnotation and Interactive::Annotations::PdfAnnotation |
PdfField |
Only one | Fields::PdfField and Interactive::Forms::PdfField |
PdfSignature |
Only one | Security::PdfSignature and Interactive::DigitalSignatures::PdfSignature |
PdfTableElement |
No such class | Spire::Pdf::Layout::Tables::PdfTableElement (new) |
Making bare names usable: open the sub-namespaces inside namespace Spire::Pdf (writing it outside only makes bare names visible;
qualified names like Spire::Pdf::Graphics::… still will not resolve to that level):
#include "Spire/Pdf/PdfDocument.h"
#include "Spire/Pdf/Graphics/PdfCanvas.h"
using namespace Spire::Pdf;
namespace Spire { namespace Pdf {
using namespace ::Spire::Pdf::Graphics; // makes bare names such as PdfCanvas, PdfFont usable
} }
62 groups of same-named types (46 classes + 16 enums) live in two different namespaces (e.g. Annotations::PdfAnnotation
and Interactive::Annotations::PdfAnnotation are both real types). You may open only one side of each group;
opening both makes the bare name immediately ambiguous (C2872), and adding a using X::PdfTable; will not suppress it either.
// ❌ Both sides opened: the bare name PdfTable is immediately ambiguous
using namespace ::Spire::Pdf::Tables;
using namespace ::Spire::Pdf::Utilities;
// ✅ Open one side only; write the other side fully qualified
using namespace ::Spire::Pdf::Tables;
intrusive_ptr<PdfTable> a = /* Tables version */;
intrusive_ptr<Spire::Pdf::Utilities::PdfTable> b = /* Utilities version */;
// ✅✅ Preferred: alias both sides in namespaces and open neither
namespace Tables = ::Spire::Pdf::Tables;
namespace Util = ::Spire::Pdf::Utilities;
intrusive_ptr<Tables::PdfTable> a;
intrusive_ptr<Util::PdfTable> b;
When the compiler reports
C2872 'X': ambiguous symbol, this is the cause — use the class name at the error location to tell which side it belongs to.
⚠ The count of 62 groups is measured on 12.10.7; swapping the DLL changes the collision surface itself, so do not treat it as a constant.
The name LPCWSTR_S is retained, but its definition changed:
typedef const wchar_t* LPCWSTR_S; // old package
typedef const char* LPCWSTR_S; // new package
Interface signatures are correspondingly unified to const std::string&:
| API | Old package | New package |
|---|---|---|
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 |
| Old form | How to change |
|---|---|
L"abc" |
Delete the L → "abc" |
LPCWSTR_S |
Can be kept (it is now const char*), or change to const char* / std::string |
std::wstring variables |
Change to std::string, and perform the encoding conversion yourself (GBK / UTF-16 → UTF-8) |
x.c_str() |
Delete it — the new interface parameter is already const std::string&, so pass it directly |
⚠
.c_str()is the easiest thing to over-add: it merely round-trips throughstd::string → const char* → std::string.
It compiles and behaves correctly, but it is unnecessary and can mislead people into thinking the interface is incompatible.
Scale for reference: LPCWSTR_S appears 1599 times in the old package headers; the new package has 809 const std::string& parameters
and 0 remaining wchar_t. MSVC requires /utf-8; the new headers contain UTF-8 Chinese comments.
PdfDestination: constructible base class → abstract base class (PdfDestinationMode is gone too)Old package: PdfDestination was a concrete class; you newed it and then set properties one by one.
intrusive_ptr<PdfDestination> dest = new PdfDestination(page);
dest->SetMode(PdfDestinationMode::Location); // old enum: Location/FitToPage/FitH/FitR/FitBH
dest->SetLocation(new PointF(0, y));
dest->SetZoom(2.f);
New package: PdfDestination is an abstract base class (protected constructor, zero public members),
PdfDestinationMode does not exist; the capability is provided by Destinations::PdfExplicitDestinationType (8 values)
and concrete subclasses, and construction becomes one-shot:
intrusive_ptr<PdfDestination> dest = new Destinations::PdfXYZExplicitDestination(page, 0, y, 2.f);
| Destination type | New package class |
|---|---|
| XYZ | Destinations::PdfXYZExplicitDestination(page, left, top[, zoom]) |
| Fit / FitH / FitV / FitR / FitB / FitBH / FitBV | Destinations::PdfFit*ExplicitDestination(…) |
Correspondingly, the constructor parameters of
PdfEmbeddedGoToActionalso changed from "a destination object" to "page number + zoom" (see 4.3).
KeyPressed)The following are measured old → new mappings (the action classes for form fields / annotations went through a round of renames on the .NET side,
and types returned by GetActions() / GetAdditionalActions() are especially likely to be affected):
| Old package | New package | Differences |
|---|---|---|
Spire::Pdf::PdfFieldActions |
Spire::Pdf::Actions::PdfFormFieldAdditionalActions |
Members renamed: GetFormat/GetValidate/GetCalculate → GetOnFormat/GetOnValidate/GetOnCalculate (setters likewise); mouse enter/exit moved up to the base class PdfAnnotationAdditionalActions (OnEnter/OnExit); KeyPressed has no replacement |
Spire::Pdf::PdfAnnotationActions |
Spire::Pdf::Actions::PdfAnnotationAdditionalActions |
Mouse / focus actions gained an On prefix: GetMouseDown → GetOnMouseDown, GetGotFocus → GetOnReceiveFocus, etc.; OnOpenPage/OnClosePage/OnShowPage/OnHidePage added; Format/Validate/Calculate are no longer on this class |
Spire::Pdf::PdfDocumentActions |
Spire::Pdf::Actions::PdfDocumentAdditionalActions |
Members changed to GetBeforeClosing/GetBeforeSaving/GetBeforePrinting/GetAfterSaving/GetAfterPrinting (old GetBeforeCloseAction etc. became gerund forms); GetAfterOpenAction has no same-named member in the new class |
Spire::Pdf::PdfEmbeddedGoToAction |
Spire::Pdf::Actions::PdfGoToEmbeddedAction |
Constructor changed to (fileName, pageNumber, zoom); GetIsNewWindow → GetNewWindow, GetFileName → GetEmbeddedFileName (read-only) |
Spire::Pdf::PdfTextFind (result object) |
Spire::Pdf::Texts::PdfTextFragment |
Search entry changed to new Texts::PdfTextFinder(page)->Find(text); GetBounds/GetPositions/GetSizes changed from single values to std::vector |
PdfDocument::GetSecurity() |
PdfDocument::GetSecurityPolicy() |
Reads go through GetSecurityPolicy(); writes go through Encrypt(policy). The old name is still exported but warns |
Spire::Pdf::License (class) |
Spire::Pdf::License::LicenseProvider (class) |
License is now a namespace; SetLicenseKey/SetLicenseFileName/ClearLicense remain, file paths use SetLicense(path), streams use SetLicense(intrusive_ptr<Stream>) |
Spire::Pdf::PdfPaperSizes |
Spire::Pdf::Print::PdfPaperSize |
Class renamed, but static constants such as A4 are still not exported (see 6.4) |
Security_PdfSignature / Utilities_PdfTable / Utilities_PdfImageInfo / Collections_PdfCollection / Security_IPdfSignatureFormatter |
Security::PdfSignature / Utilities::PdfTable / Utilities::PdfImageInfo / Collections::PdfCollection / … |
The old package used prefix names for disambiguation; the new package distinguishes by namespace, and the bare names are unchanged |
// Old package
intrusive_ptr<PdfFieldActions> actions = field->GetActions();
actions->SetFormat(jsAction);
actions->SetKeyPressed(jsAction);
// New package
intrusive_ptr<Actions::PdfFormFieldAdditionalActions> actions = field->GetActions();
actions->SetOnFormat(jsAction);
// SetKeyPressed: no corresponding member
The old package's two action classes have a "base class + derived class" relationship in the new API
(PdfFormFieldAdditionalActions : PdfAnnotationAdditionalActions); their members overlap, so just look up the mapping in the table above.The above are examples, not the complete set. For other cross-version renames on the .NET side, simply follow the compiler errors (if the name is missing, it was renamed),
and the compiler will point directly at the type/member.
KeyPressed has no replacement:
| API | Old package | New package | Conclusion |
|---|---|---|---|
KeyPressed (JS action of form fields / annotations) |
PdfFieldActions::Get/SetKeyPressed, PdfAnnotationActions::Get/SetKeyPressed |
None | Removed from the .NET API by the vendor, no replacement; that part of the logic must be redesigned |
Within the scope covered by the vendor's demo suite, all other old members still have a corresponding form.
Cold types not covered by the demos may have other .NET cross-version differences — treat compiler errors as authoritative; this document does not claim "zero gaps other thanKeyPressed".
Object: type checking and downcasting (including behavioral changes)| Member | Old package | New package |
|---|---|---|
GetInstanceTypeName() |
public, returns the C++ mangled name (typeid(T).name()) |
private (calling it gives C2248), and its content is the managed full name |
ManagedName() |
Does not exist | private (used only internally by the generator) |
CheckType<T>(p) |
public | public, semantics unchanged (true/false) |
Dynamic_cast<T>(p) |
boost cast; on failure falls back to unvalidated retagging ⇒ never returns null | boost cast only: returns null on failure |
Convert<T>(p) |
Unvalidated retagging; returns non-null even for the wrong type | Checked: throws SpireTypeError on failure (carrying Actual() / Target()) |
UncheckedCast<T>(p) |
Does not exist | New explicit escape hatch (still unvalidated retagging) |
// Old package: compare by type-name string, then cast without validation
if (widget->GetInstanceTypeName() == /* some name */) { /* … */ }
intrusive_ptr<PdfNewPage> page = Object::Convert<PdfNewPage>(doc->GetPages()->Add()); // never fails
// New package: three checked forms
if (Object::CheckType<PdfNewPage>(obj)) { /* only need yes/no */ }
if (auto page = Object::Dynamic_cast<PdfNewPage>(obj)) { // not that type → nullptr
page->DoSomething();
}
try {
auto page = Object::Convert<PdfNewPage>(obj); // not that type → throws
page->DoSomething();
}
catch (const SpireTypeError& e) {
// e.Actual() = actual managed full name; e.Target() = expected full name
}
⚠ Key behavioral change: the old
Convert"counted success even if it mislabeled the object"; the newConvertthrows on the spot.
The oldDynamic_castsilently returned an object "with a new label" on failure; the newDynamic_castreturnsnullptr.
Code migrated from the old package that relies on "never null" must add null checks, or switch toConvert+ exception handling.
| API | Old package return | New package return |
|---|---|---|
PdfField::GetFullName() |
LPCWSTR_S (wide characters) |
std::string (UTF-8) |
Pdf3DAnnotation::Get_3DData() |
intrusive_ptr<Stream> |
std::vector<uint8_t> |
GetBounds/GetPositions/GetSizes of Texts::PdfTextFragment |
The old PdfTextFind counterpart GetBounds/GetPosition/GetSize, all single values |
std::vector<intrusive_ptr<…>> |
The old package exported add_* / remove_* accessors for 19 events across 10 classes, for example:
add_PageAdded / remove_PageAdded
add_BeginPageLayout / remove_BeginPageLayout
add_BeginPrint / add_EndPrint
add_QueryRowCount / add_QueryNextRow
add_SaveProgress / add_PaperSettings
In the new package's C++ Spire/Pdf/** these accessors do not exist at all (measured: add_* only matches the unrelated add_ref).
Note, however, that event registration in the old package was already incomplete: 15 of the 16 *EventHandler classes have their Invoke commented out
(//virtual void Invoke (…)), so customers could not implement callbacks; only BeginRowLayoutEventHandler has an
implementable virtual void Invoke(...). Therefore:
Invoke, but there is no registration entry point);Also:
*EventArgs / *EventHandler classes themselves are still in the new package's export surface (32 class names), and Invoke is actually generated this time;Spire.Pdf.C.h contains 12 _add_ exports
(e.g. PdfTable_add_BeginCellLayout, PdfLayoutWidget_add_BeginPageLayout, PdfPageBase_add_BeginSave);Spire.Pdf.C.h is an internal interop header, not a public C API ⇒ C++ code that relies on events must be redesigned;
do not expect that "renaming a class is enough to register".Comparing by class base name, 156 old class names no longer appear in the new package. Do not read this as 156 capabilities disappearing:
Security_PdfSignature, Utilities_PdfTable, Utilities_PdfImageInfo,
Collections_PdfCollection, Security_IPdfSignatureFormatter) — the new package distinguishes them by namespace, and the bare names are unchanged;PdfFieldActions, PdfAnnotationActions, PdfEmbeddedGoToAction,
PdfTextFind, PdfDocumentActions, PdfPaperSizes, License, etc.);| Category | Representative classes | Notes |
|---|---|---|
| Base value types / collection interfaces | Byte, Char, Int16, Int64, Single, UInt16/32/64, DictionaryEntry, ICollection, IDictionary, IDictionaryEnumerator, IList, List, SpireString |
Wrapper classes are no longer needed: strings use std::string, integers use native types, collections use the native protocol; String / Decimal are exported separately |
| Internal implementation / serialization / format conversion | ZipArchive*, ZippedContentStream, ZlibZipWriter, XmpMetadata/XmpSchema/XmpStructure (→ PdfXmpMetadata / PdfXmpNamespace), Story*, FixedDocument/FixedPage/Glyphs, HtmlConverter/HtmlToPdf*, Qt_HtmlConverter, TranslatorFactory |
Implementation classes leaked by the old package; the new package does not export them |
| Drawing / XPS / WPF model (.NET types leaked by the old package) | Brush, Canvas, Geometry, Path, PathFigure, PathGeometry, MatrixTransform, GradientStop(s), SolidColorBrush, ImageBrush, Visual, Resources |
Not part of the PDF public API; the new package does not export them |
| PDF types refactored / removed by the vendor | PdfGraphicsState, PdfImageMask, PdfHTMLTextElement, PdfHtmlLayoutFormat, PdfPaperSourceTray, PdfButtonWidgetWidgetItem, PdfTexBoxWidgetItem, etc. |
Already renamed / removed on the vendor's .NET API side; treat compiler errors as authoritative |
The constants in the old package's
PdfPaperSizes(Letter/A4…) were commented out entirely and were never exported in either generation (see 6.4).
| Functional area | Representative classes |
|---|---|
| Document comparison | PdfComparer, PdfCompareOptions |
| Content building / drawing | PdfContentBuilder, PdfContentResult, PdfDrawer, PdfAppearances, PdfAppearanceCharacteristics, PdfDefaultAppearance, PdfFreeTextAppearanceBuilder, PdfWatermarkAppearanceBuilder, PdfWatermarkInfo, PdfHatchBrush, PdfIconFit |
| Layout elements (tables / charts / paragraphs) | 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 |
| Chart elements | PdfBarChartElement/PdfBarChartStyle, PdfLineChartElement/PdfLineChartStyle, PdfPieChartElement/PdfPieChartStyle, PdfScatterChartElement/PdfScatterChartStyle, PdfStackedBarChartElement/PdfStackedBarChartStyle, PdfHistogramElement/PdfHistogramStyle |
| Barcodes | PdfBarcodeElement, PdfBarcodeStyle, PdfInlineBarcode |
| Annotations | PdfCaretAnnotation, PdfCircleAnnotation, PdfFileAttachmentAnnotation, PdfHighlightAnnotation, PdfUnderlineAnnotation, PdfStrikeOutAnnotation, PdfSquigglyAnnotation, PdfSquareAnnotation, PdfPolyAnnotation, PdfPolylineAnnotation, PdfRedactionAnnotation, PdfTextAnnotation, PdfWidgetAnnotation(Collection), PdfMarkupAnnotation |
| Forms | PdfChoiceField, PdfChoiceItem(Collection), PdfPushButtonField, PdfRadioButtonField, PdfTextField, XfaForm + Xfa{Barcode,Button,CheckBox,Choice,ComboBox,DateTime,Image,ListBox,Numeric,RadioButton,Signature,Text}Field |
| 3D / rich media | Pdf3DArtwork, Pdf3DLightingScheme, Pdf3DRenderMode, PdfRichMediaAnnotation, PdfRichMediaAnnotationWidget, PdfRichMediaContent, PdfMovie, PdfMovieAnnotation, PdfScreenAnnotation |
| Security / signatures / metadata | PdfSecurityPolicy, PdfPasswordSecurityPolicy, PdfDocumentPrivilege, PdfXmpMetadata, PdfXmpNamespace |
| Converters / export options | PdfToImageConverter, PdfToMarkdownConverter, PdfToSvgConverter, PdfToWordConverter, MarkdownOptions, SvgOptions, PptxOptions, OfdOptions, MetafileOptions, RenderingOptions, IgnoreOptions, ImageCompressionOptions, XlsxSpecialTableLayoutOptions |
| Destinations | PdfExplicitDestination + PdfXYZExplicitDestination, PdfFitExplicitDestination, PdfFitH/V/R/B/BH/BVExplicitDestination (8 concrete subclasses in total) |
| Actions | PdfAnnotationAdditionalActions, PdfDocumentAdditionalActions, PdfFormFieldAdditionalActions, PdfGoToEmbeddedAction, PdfHideAction, PdfResetFormAction, PdfSubmitFormAction, PdfURIAction |
| Fonts / printing | PdfFontStore, PdfEmbeddedFontConverter, PdfFontFamilySpec, PdfPaperSize, DefaultPrintLogger, PdfHeaderFooter |
| Files / import-export | PdfEmbeddedFile, PdfFileSpecification, PdfFormExportResult, PdfFormImportResult, PdfFixedPrint |
| Base types | String, Decimal, LicenseProvider |
| Other | PdfAnchorEntry, PdfAnchorRegistry, PdfNavigationEntry, PdfNavigationRegistry, PdfCollectionItem, PdfImageInfo, PdfNumberFormatter, PdfStandardOptions, PdfThemeProfile, PdfRectangleDifferences, PdfDynamicData, TSAResponse, BitmapOptions |
The old package could only use GetCount() + GetItem(i) (some collections did not even have GetCount, so they could not be enumerated);
while keeping GetCount/GetItem, the new package's List<T>-derived collections additionally provide the native collection protocol:
// Old package
intrusive_ptr<PdfPageCollection> pages = doc->GetPages();
for (int i = 0; i < pages->GetCount(); ++i) {
intrusive_ptr<PdfPageBase> page = pages->GetItem(i);
}
// New package (the old style still works; below is the more idiomatic style)
for (intrusive_ptr<PdfPageBase> page : *doc->GetPages()) { /* … */ }
int n = doc->GetPages()->size();
intrusive_ptr<PdfPageBase> first = (*doc->GetPages())[0];
doc->GetPages()->RemoveAt(0); // when the collection supports it
⚠ Every access goes back to the same managed collection (live-object semantics, not a snapshot).
⚠ Do not test "same element" by comparing handle pointers — each getter creates a new handle; compare state instead.
Jagged arrays T[][] go from "not exported" to 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, returns the same table
std::vector<std::vector<int>> ink = {{1,2,3}, {}}; // empty inner vector is valid
intrusive_ptr<Annotations::PdfInkAnnotation> ann = new Annotations::PdfInkAnnotation(ink);
std::vector<std::vector<int>> back = ann->GetInkList();
Dictionaries Dictionary<K,V> go from "non-enumerable handles / not exported" to native std::map<K,V>:
std::map<std::string, std::string> props =
doc->GetDocumentInformation()->GetAllCustomProperties();
// Values are wrapped by their true managed type, not bare Object
std::map<Security::SignInfoType, intrusive_ptr<Object>> fonts;
fonts[Security::SignInfoType::DigitalSigner] = new Common::String("Times New Roman");
sig->SetSignInfoFont(fonts);
null and empty are distinguishable: on the C++ side use the companion
GetX(bool& isNull)/SetX(std::nullptr_t)overloads (measured: 54 / 54 signatures, across 46 classes).
[Obsolete]) APIs: still exported, but emit compiler warningsMembers that the vendor marked [Obsolete] on the .NET side are still exported as usual in the new package (72 declarations across 17 classes),
with only a SPIRE_DEPRECATED("…vendor text…") added before the declaration:
/W3 (the VS project default), invisible at /W1;-Wdeprecated-declarations by default.| Class | Obsolete member | Suggested replacement |
|---|---|---|
PdfDocument |
GetSecurity() |
GetSecurityPolicy() + Encrypt(policy) |
PdfDocument |
The document-returning MergeFiles(…) overload |
static void MergeFiles(inputFiles, outputFile) (releases resources automatically) |
PdfViewerPreferences |
SetBookMarkExpandOrCollapse(bool) |
PdfBookmark::SetExpandBookmark(bool) |
PdfUnidimensionalBarcode |
GetEnableCheckDigit() / GetShowCheckDigit() |
None (the vendor provided no replacement) |
PdfSignatureMaker |
12 Set{Name,Location,Reason,Date,ContactInfo,DistinguishedName}{,Label} |
Same-named properties on PdfSignature / PdfSignatureAppearance |
PdfTrueTypeFont |
The PdfTrueTypeFont(fontFile, size[, style]) constructor |
PdfTrueTypeFont::FromFontFile(path, size[, style]) |
Do not globally suppress these with
/wd4996or-Wno-deprecated-declarations— these warnings are the upgrade roadmap.
include/Spire.Pdf.C.h is a new interop form added by the new package: 6398 SPIRE_PDF_API function declarations
serving the interop between the AOT native library and the C++ wrapper. It is not a public C API like the one in the DOC package:
int*, strings are UTF-8 const char*, and a trailing int** is the exception slot;Spire/Pdf/**;Scanning through in order covers the vast majority of changes:
| # | Search for | Change to | Notes |
|---|---|---|---|
| 1 | #include <Spire.Pdf.o.h> |
Include the concrete headers on demand (#include "Spire/Pdf/<path>.h") |
See 3.1 |
| 2 | Missing -I in the compile command |
Add include + include/Spire/Pdf + include/Spire/Pdf/common/h |
See 3.1 |
| 3 | L" |
" (remove the L) |
See 4.1 |
| 4 | .c_str() |
Pass the std::string directly |
Delete it; the new interfaces do not need it |
| 5 | LPCWSTR_S |
Can be kept (it is now const char*) |
If you declared wide-character variables, change them to std::string |
| 6 | std::wstring |
std::string |
Watch the encoding conversion (UTF-16 / GBK → UTF-8) |
| 7 | GetInstanceTypeName() / ManagedName() |
CheckType<T> / Dynamic_cast<T> / Convert<T> |
Both accessors are now private; see 4.4 |
| 8 | Code relying on Object::Convert<T> "never failing" |
Add null checks, or switch to CheckType / Dynamic_cast |
The new Convert throws SpireTypeError |
| 9 | new PdfDestination( |
Construct a concrete destination subclass | See 4.2 |
| 10 | PdfDestinationMode |
PdfExplicitDestinationType / a concrete subclass |
See 4.2 |
| 11 | PdfFieldActions / PdfAnnotationActions |
Actions::PdfFormFieldAdditionalActions / …AdditionalActions |
See 4.3 |
| 12 | PdfDocumentActions |
Actions::PdfDocumentAdditionalActions |
Member names also change; see 4.3 |
| 13 | PdfEmbeddedGoToAction |
Actions::PdfGoToEmbeddedAction |
Constructor and properties both change; see 4.3 |
| 14 | PdfTextFind |
Texts::PdfTextFragment + Texts::PdfTextFinder |
Search entry and return types both change; see 4.3 / 4.5 |
| 15 | GetKeyPressed / SetKeyPressed |
No replacement | See 4.3; requires redesign |
| 16 | License::SetLicenseKey etc. |
License::LicenseProvider::SetLicenseKey etc. |
License is now a namespace; see 4.3 |
| 17 | GetSecurity() |
GetSecurityPolicy() + Encrypt(policy) |
The old one still works but warns |
| 18 | add_* / remove_* event accessors |
No C++ entry points | Most old callbacks were unusable too (only row-layout events could be registered); see 4.6 |
| 19 | PdfPaperSizes |
Print::PdfPaperSize |
Class renamed, but constants such as A4 are still unavailable; see 6.4 |
| 20 | Bare byte (vector<byte>) |
unsigned char |
Only needed for C++17 and above |
| 21 | PdfPaperSize::A4 etc. |
PdfPageSize::A4() |
Missing in both generations; not a regression |
| 22 | Compiler reports C2872 ambiguous |
Use fully qualified names or namespace aliases per 3.3 | 62 groups of same-named types |