Examples / pdf_to_text / activex_cpp

Pdf To Text

A complete, runnable activex_cpp program — 98 lines, shipped in your download.

Demonstrates Text

Same example, other languages: c cpp cpp_linux csharp delphi python vbnet

examples/activex_cpp/pdf_to_text/pdf_to_text.cpp 98 lines
// ============================================================================
//  pdf_to_text -- C++ ActiveX (COM) port, GENERATED by
//  tools/gen_activex_cpp_examples.py from examples/cpp/pdf_to_text/pdf_to_text.cpp
//
//  DO NOT EDIT BY HAND unless you also fix the generator: the next run
//  overwrites this file. If a case cannot be expressed mechanically, teach the
//  generator the rule -- that is what keeps the other 87 honest.
//
//  This drives the SAME engine as examples/cpp/pdf_to_text/pdf_to_text.cpp, but through the COM
//  object wrappers/activex exposes rather than the flat C API, so it exercises
//  the marshalling layer no compiled language exercised before.
// ============================================================================
#import "..\\..\\..\\wrappers\\activex\\LumasPdfAX.tlb" no_namespace named_guids

#include <windows.h>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>

// Output goes beside the EXECUTABLE, at the same relative path delphi's lands
// at, because tools/compare_lang_outputs.py keys on exactly that.
static std::string exeDir() {
    char buf[MAX_PATH];
    GetModuleFileNameA(nullptr, buf, MAX_PATH);
    std::string s(buf);
    size_t p = s.find_last_of("\\/");
    return p == std::string::npos ? std::string(".") : s.substr(0, p);
}

// pdf_to_text -- C++ port of examples\Vb6\pdf_to_text\pdf_to_text.bas
// Imports a PDF and extracts each page's text (pdfSplitPageTextA) to out.txt.

#include "repo_root.h"
#include <cstdio>
#include <string>

static const unsigned long emNoFuncNames = 0x10000000; // not in the wrapper enum; from LumasPdf.pas





int main(int argc, char** argv) {
    (void)argc; (void)argv;
    if (FAILED(CoInitialize(nullptr))) return 1;
    int _rc = 0;
    try {
    ILumasPDFPtr pdf;
    if (FAILED(pdf.CreateInstance(L"LumasPdf.PDF")))
        _com_issue_error(E_FAIL);
    pdf->RaiseExceptions = VARIANT_TRUE;
    pdf->SetErrorMode(emNoFuncNames);

    std::string cmapDir = exeDir() + "/CMap";
    pdf->SetCMapDirA(cmapDir.c_str(), lcmRecursive | lcmDelayed);

    if(pdf->CreateNewPDFA("") == 0){ pdf->DeletePDF(); return 1; }

    pdf->SetImportFlags(ifContentOnly | ifImportAsPage);
    const char* inFile = LUMAS_REPO_ROOT "/sample_multipage.pdf";
    if(pdf->OpenImportFileA(inFile, ptOpen, "") < 0){ pdf->FreePDF(); pdf->DeletePDF(); return 1; }
    if(pdf->ImportPDFFile(1, 1.0, 1.0) < 0){ pdf->FreePDF(); pdf->DeletePDF(); return 1; }
    pdf->CloseImportFile();

    std::string outFile = exeDir() + "/out.txt";
    FILE* fp = fopen(outFile.c_str(), "w");
    if(!fp){ pdf->FreePDF(); pdf->DeletePDF(); return 1; }

    long count = pdf->GetPageCount();
    for(long i = 1; i <= count; ++i){
        fprintf(fp, "----- Page %d -----\n", i);
        pdf->EditPage(i);
        _bstr_t _bs_txt = pdf->SplitPageText(i);
        const char* txt = (const char*)_bs_txt;
        fprintf(fp, "%s\n", txt ? txt : "");
        pdf->EndPage();
    }

    fclose(fp);
    pdf->FreePDF();
    printf("Text written to: %s\n", outFile.c_str());

    return 0;
    } catch (const _com_error& e) {
        const _bstr_t d = e.Description();
        if (d.length())
            std::fprintf(stderr, "COM error 0x%08lx: %ws\n",
                         (unsigned long)e.Error(), (const wchar_t*)d);
        else
            std::fprintf(stderr, "COM error 0x%08lx: %s\n",
                         (unsigned long)e.Error(), e.ErrorMessage());
        _rc = 1;
    }
    CoUninitialize();
    return _rc;
}

This file is in the SDK at examples/activex_cpp/pdf_to_text/pdf_to_text.cpp. The build fails if this page and that file ever differ.