BCL easyPDF SDK
easyPDF SDK Usermanual
PDF Creator Programming API  |  Download Free Trial  |  Contact Us to Purchase

Native C PDFProcessor API

Getting Help

The C API is inherently very large and obscure. However, the objects and the methods are all similar to the C# and COM APIs.

If you are just starting with easyPDF SDK, consider using C#, VB, PHP or Python for your initial testing and prototyping. You will be up to speed much quicker.

If you are ready to dive into C/C++, we recommend that you study the header file located at c:\Program Files\Common Files\BCL Technologies\easyPDF 8\include\easyPDFProcessor.h.

If you have any questions, please don't hesitate to submit a support ticket.

Usage

The native C API is very similar to the COM API, with a few distinct differences.

Objects are implemented as C structures, and member functions and properties are achieved via function pointers inside each structure. This allows for a syntax that is very close to C++ classes.

According to our naming convention, all easyPDF macros and enumerations begin with BCL_, and all global functions and types begin with Bcl. Therefore the PDFProcessor class is really called BclPDFProcessor.

Note that the PDFProcessor class and the PDFProcessorHandle class are vastly different. Completely different rules apply to them.

PDFProcessor is a stateless singleton object, which means it has no internal variables, and only one instance of this object can be created for the entire application. Memory allocated is not managed automatically.

PDFProcessorHandle is more like the rest of the easyPDF SDK. It has an internal state, and multiple instances of this class can be created. Memory allocated is managed automatically.

PDFProcessor Usage

easyPDFProcessor.dll exports only a single function called BclGetPDFProcessor, which is responsible for getting the BclPDFProcessor object. All other functions and properties are called via the BclPDFProcessor object.

The BclGetPDFProcessor function has the following prototype:

const struct BclPDFProcessor* BclGetPDFProcessor();

The pointer returned by BclGetPDFProcessor must never be explicitly deleted. BclPDFProcessor is a singleton object with no internal state, which means only a single copy of this object is ever created. The object has no internal variables, only static methods. Each function call is re-entrant.

Here is an example that gets the number of pages in a PDF file:

const BclPDFProcessor* pProcessor = BclGetPDFProcessor();
if(!pProcessor)
   goto Error;
int pageCount = 0;
BclPrcResult error = pProcessor->GetPageCount(NULL, L"c:\\test\\input.pdf", L"", &pageCount);
if(error)
   goto Error;

You may call a method just like in C++. pProcessor->GetPageCount is a function pointer to the method, and the first parameter is a BclPDFProcessorSettings pointer, which can be NULL for default settings. Since the BclPDFProcessor class is stateless, it won't remember anything in between function calls, therefore all settings must be passed to each individual function call.

Almost every method returns an error result type called BclPrcResult. The actual return value of the function is retrieved via a pointer, just like in COM.

Error handling must be implemented for each individual method call. If there is no error, the return value is BCL_PRC_R_SUCCESS, which has a value of 0. All errors have a negative value.

If you are programming in C++, feel free to translate errors into your own exceptions:

if(error)
   throw std::runtime_error(pProcessor->PrcResultToAscii(error));

PrcResultToAscii and PrcResultToString are two of the few functions that don't follow the regular method calling convention. They take a single BclPrcResult input, and return a human-readable error message. PrcResultToAscii returns const char*, while PrcResultToString returns const wchar_t*. Never deallocate these strings, because they are static constants!

Note that BclPDFProcessor has two variables, LibraryVersionMajor and LibraryVersionMinor. However, they are considered read-only constants, as opposed to internal state variables. BclPDFProcessor has no internal state, only methods and constants, which are assigned once and never change.

PDFProcessor Memory Management

BclPDFProcessor has no automatic memory management. All pointers returned must be deallocated manually, using the BclPDFProcessor::ReleasePtr method, which has the following prototype:

void ReleasePtr(void* p);

There is a single parameter, the pointer to be deallocated. Only pass pointers returned by one of the PDFProcessor SDK methods.

Exception: Pointers returned by the PrcResultToAscii and PrcResultToString must never be deallocated!

Note that BclPDFProcessor::ReleasePtr is not the same as BclPDFProcessorHandle::ReleasePtr. One deallocates memory from PDFProcessor, while the other one releases pointers from PDFProcessorHandle. They are two completely separate APIs.

Also note that all pointers returned by the SDK point to constant memory and must not be modified. For example, strings returned are constant. If you need to modify them, make your own copy, and apply the modifications there.

PDFProcessorHandle Usage

In order to create a PDFProcessorHandle object, first you must get a PDFProcessor object, and call its OpenFile or OpenMem method:

const BclPDFProcessor* pProcessor = BclGetPDFProcessor();
if(!pProcessor)
   goto Error;
int pageCount = 0;
BclPDFProcessorHandle* pHandle = NULL;
BclPrcResult error = pProcessor->OpenFile(NULL, L"c:\\test\\input.pdf", L"c:\\test\\output.pdf", L"", &pHandle);
if(error || !handle)
   goto Error;
error = pHandle->GetPageCount(pHandle, &pageCount);
if(error)
   goto Error;
...
pHandle->Dispose(handle);

All successfully opened handles must be explicitly deallocated using the Dispose method. All other pointers are managed automatically.

Most PDFProcessorHandle methods return of type BclPrcResult, which is used for error handling. Also the first argument of most methods is a BclPDFProcessorHandle pointer, which must be the pHandle object itself. This is similar to self in Python, and this in PHP, C# and C++. Even in C++, you must explicitly pass this parameter. In other words, a method that has no parameters still has a single argument, the pHandle pointer.

PDFProcessorHandle Memory Management

With the exception of the BclPDFProcessorHandle pointer returned by OpenFile or OpenMem, memory management is completely automatic. You are not required to manually deallocate any pointer returned by the PDFProcessorHandle SDK, with the exception of pHandle itself, whose Dispose method must be called explicitly. Failure to properly dispose the handle will cause the SDK to stay in memory indefinitely, until your application quits. This can be a huge burden, especially when OpenFile or OpenMem is called repeatedly without properly disposing of the pointer.

The good news is that PDFProcessorHandle internally keeps track of all pointers that it allocates, and Dispose automatically takes care of all the deallocations. Most people will never have to worry about deallocating individual pointers other than pHandle.

There are two notable exceptions:

  1. If you are calling a very large number of functions that return strings or memory buffers, without calling Dispose in between.
  2. If you are calling functions that return potentially very large memory buffers, without calling Dispose shortly thereafter.

Strings and memory streams allocated by the SDK may be explicitly deallocated using the BclPDFProcessorHandle::ReleasePtr method, which has the following prototype:

void ReleasePtr(struct BclPDFProcessorHandle* pHandle, void* p);

The first parameter is the pHandle that was used to allocate the string or buffer. The second parameter is the pointer to be deallocated. If you have multiple pHandle pointers alive, it is essential to pass the one which did the allocation, because each BclPDFProcessorHandle object has a completely independent memory manager. Whatever memory was not deallocated via ReleasePtr will be deallocated by Dispose. Obviously, after the Dispose method is called, all related SDK pointers become invalid and unusable.

Never call ReleasePtr on pHandle itself! pHandle must be deallocated using Dispose, all other SDK strings and buffers must be deallocated using ReleasePtr, or not deallocated at all. Never call free(), delete, VirtualFree or other operating system functions on SDK pointers!

Note that BclPDFProcessor::ReleasePtr is not the same as BclPDFProcessorHandle::ReleasePtr. One deallocates memory from PDFProcessor, while the other one releases pointers from PDFProcessorHandle. They are two completely separate APIs.

Also note that all pointers returned by the SDK point to constant memory and must not be modified. For example, strings returned are constant. If you need to modify them, make your own copy, and apply the modifications there.

Launch Timeout

Launching the worker process and connecting the named pipe should happen very fast, in milliseconds. However, under an abnormally heavy load, the computer may not have enough cycles to perform this task in a timely fashion.

The Native C API has an internal timeout built-in. The default value is 1 minute. This is because a server may momentarily slow down so much that it is not responding for seconds, but it usually recovers after a while.

The default timeout value can be changed via BclLoaderSettings::LaunchTimeout (in milliseconds). This can be done by passing LoaderSettings via BclPDFProcessorSettings to each method in PDFProcessor:

BclPDFProcessorSettings processorSettings = { 0 };
processorSettings.LoaderSettings.LaunchTimeout = 60000; // 1 minute
error = pProcessor->GetPageCount(&processorSettings, &pageCount);

In the PDFProcessorHandle API, the same settings should be passed to OpenFile or OpenMem, which in turn pass these settings to the BclPDFProcessorHandle object.

Upon timeout, an exception is thrown. Another attempt may be made later.