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

Native C API

In addition to the standard COM API, easyPDF SDK is also available as a native C API.

Note: there is no native C API for the PDFDocument SDK yet.

Rationale

Almost every language has a way of calling C functions, therefore the C API is our most universal interface. We provide both 32-bit and 64-bit DLLs.

The native C API works by launching an external worker process (also known as a sandbox). This external process is completely isolated. Named pipes are used for communication in between the customer's code and the sandbox.

There are numerous advantages to using this new native C API, instead of the older COM objects:

There are no known disadvantages to using the native C API versus the COM interop API.

Files

The native C API consists of the following files:

c:\Program Files\Common Files\BCL Technologies\easyPDF 8\include\easyPDFPrinter.h
c:\Program Files\Common Files\BCL Technologies\easyPDF 8\include\easyPDFProcessor.h
c:\Program Files\Common Files\BCL Technologies\easyPDF 8\include\easyPDFConverter.h
c:\Program Files\Common Files\BCL Technologies\easyPDF 8\easyPDFPrinter.dll
c:\Program Files\Common Files\BCL Technologies\easyPDF 8\easyPDFProcessor.dll
c:\Program Files\Common Files\BCL Technologies\easyPDF 8\easyPDFConverter.dll
c:\Program Files (x86)\Common Files\BCL Technologies\easyPDF 8\easyPDFPrinter.dll
c:\Program Files (x86)\Common Files\BCL Technologies\easyPDF 8\easyPDFProcessor.dll
c:\Program Files (x86)\Common Files\BCL Technologies\easyPDF 8\easyPDFConverter.dll

32-bit applications on 64-bit Windows must use the following DLLs:

c:\Program Files (x86)\Common Files\BCL Technologies\easyPDF 8\easyPDFPrinter.dll
c:\Program Files (x86)\Common Files\BCL Technologies\easyPDF 8\easyPDFProcessor.dll
c:\Program Files (x86)\Common Files\BCL Technologies\easyPDF 8\easyPDFConverter.dll

In all other cases, the following DLLs must be used:

c:\Program Files\Common Files\BCL Technologies\easyPDF 8\easyPDFPrinter.dll
c:\Program Files\Common Files\BCL Technologies\easyPDF 8\easyPDFProcessor.dll
c:\Program Files\Common Files\BCL Technologies\easyPDF 8\easyPDFConverter.dll

Locating the DLLs

We are not providing LIB files. Instead, the functionality is implemented in DLLs, which must be loaded dynamically.

The first step is to locate the DLLs on your system. Although you could hard-code the physical path, that is considered bad practice. We are going to show you how to find the DLLs dynamically, regardless of where easyPDF is installed. This requires quite a bit of code, but this is the most robust solution.

You are not required to understand this code. For now, please just accept that the following code is the best way of locating the DLLs. In the next section, we are going to show you how to use these functions.

// Gets a string value from the registry
// hKeyRoot:  [in] one of: HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, HKEY_CLASSES_ROOT
// subKey:    [in] path to the registry key to read
// name:      [in] name of the registry value to read
// value:     [out] the retrieved value (must be valueSize characters long)
// valueSize: [in] the maximum number of characters that value can hold (including the terminating \0)
// returns: TRUE for success; FALE for failure
static BOOL GetStringFromRegistry(HKEY hKeyRoot, LPCTSTR subKey, LPCTSTR name, LPTSTR value, unsigned valueSize)
{
   HKEY hKey;
   BOOL result = FALSE;

   if(!subKey || !name || !value || valueSize == 0)
      return FALSE;

   if(RegOpenKeyEx(hKeyRoot, subKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
   {
      DWORD type = 0;
      DWORD size = 0;

      if(RegQueryValueEx(hKey, name, 0, &type, 0, &size) == ERROR_SUCCESS && (type == REG_SZ || type == REG_EXPAND_SZ) && size > 0)
      {
         memset(value, 0, valueSize * sizeof(TCHAR));
         size = valueSize * sizeof(TCHAR);

         if(RegQueryValueEx(hKey, name, 0, &type, (LPBYTE)value, &size) == ERROR_SUCCESS)
            result = TRUE;
      }

      RegCloseKey(hKey);
   }

   return result;
}


// Detects if a particular process is running under Wow64 (32-bit process on Win64)
// hProcess: [in] handle to a process
// returns:  TRUE hProcess is 32-bit under Win64; FALSE otherwise; FALSE on 32-bit Windows
static BOOL IsWow64Proc(HANDLE hProcess)
{
   typedef BOOL (WINAPI * PtrIsWow64Process)(HANDLE, PBOOL);
   BOOL is64 = FALSE;
   PtrIsWow64Process fnIsWow64Process = (PtrIsWow64Process)(
      GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process"));
   return fnIsWow64Process && fnIsWow64Process(hProcess, &is64) && is64;
}

// Gets the easyPDF library path
// path: [out] path to the easyPDF DLLs; must be MAX_PATH characters large
// returns TRUE on success, FALSE on failure
static BOOL GetEasyPDFPath(TCHAR* path)
{
   const TCHAR* keyName;
   if(IsWow64Proc(GetCurrentProcess())) // 32-bit process on 64-bit Windows
      keyName = _T("ProgramPath32");
   else if(sizeof(void*) == 8) // 64-bit process on 64-bit Windows
      keyName = _T("ProgramPath64");
   else // 32-bit process on 32-bit Windows
      keyName = _T("ProgramPath");
   return GetStringFromRegistry(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\BCL Technologies\\easyPDF 8"), keyName, path, MAX_PATH);
}

// Gets the easyPDF Printer DLL file name
// path: [out] file name for the easyPDF Printer DLL; must be MAX_PATH characters large
// returns TRUE on success, FALSE on failure
static BOOL GetEasyPDFPrinterDLLFileName(TCHAR* path)
{
   if(!GetEasyPDFPath(path))
      return FALSE;
   _tcsncat_s(path, MAX_PATH, _T("easyPDFPrinter.dll"), MAX_PATH);
   path[MAX_PATH - 1] = '\0';
   return TRUE;
}

// Gets the easyPDF Processor DLL file name
// path: [out] file name for the easyPDF Processor DLL; must be MAX_PATH characters large
// returns TRUE on success, FALSE on failure
static BOOL GetEasyPDFProcessorDLLFileName(TCHAR* path)
{
   if(!GetEasyPDFPath(path))
      return FALSE;
   _tcsncat_s(path, MAX_PATH, _T("easyPDFProcessor.dll"), MAX_PATH);
   path[MAX_PATH - 1] = '\0';
   return TRUE;
}

// Gets the easyPDF PDFConverter DLL file name
// path: [out] file name for the easyPDF PDFConverter DLL; must be MAX_PATH characters large
// returns TRUE on success, FALSE on failure
static BOOL GetEasyPDFConverterDLLFileName(TCHAR* path)
{
   if(!GetEasyPDFPath(path))
      return FALSE;
   _tcsncat_s(path, MAX_PATH, _T("easyPDFConverter.dll"), MAX_PATH);
   path[MAX_PATH - 1] = '\0';
   return TRUE;
}

static BOOL GetEasyPDFProcessorDLL(wchar_t* path)
{
   if(!GetEasyPDFPath(path))
      return FALSE;
   wcsncat_s(path, MAX_PATH, L"easyPDFProcessor.dll", MAX_PATH);
   path[MAX_PATH - 1] = 0;
   return TRUE;
}

static BOOL GetEasyPDFConverterDLL(wchar_t* path)
{
   if(!GetEasyPDFPath(path))
      return FALSE;
   wcsncat_s(path, MAX_PATH, L"easyPDFConverter.dll", MAX_PATH);
   path[MAX_PATH - 1] = 0;
   return TRUE;
}

// Loads the easyPDF Printer DLL
// returns a handle to the easyPDF Printer DLL, or NULL on failure
static HMODULE LoadEasyPDFPrinterDLL()
{
   TCHAR dllFileName[MAX_PATH] = { 0 };
   if(!GetEasyPDFPrinterDLLFileName(dllFileName))
      return NULL;
   else
      return LoadLibrary(dllFileName);
}

// Loads the easyPDF Processor DLL
// returns a handle to the easyPDF Processor DLL, or NULL on failure
static HMODULE LoadEasyPDFProcessorDLL()
{
   TCHAR dllFileName[MAX_PATH] = { 0 };
   if(!GetEasyPDFProcessorDLLFileName(dllFileName))
      return NULL;
   else
      return LoadLibrary(dllFileName);
}

// Loads the easyPDF PDFConverter DLL
// returns a handle to the easyPDF PDFConverter DLL, or NULL on failure
static HMODULE LoadEasyPDFConverterDLL()
{
   TCHAR dllFileName[MAX_PATH] = { 0 };
   if(!GetEasyPDFConverterDLLFileName(dllFileName))
      return NULL;
   else
      return LoadLibrary(dllFileName);
}

// Create a new BclPrinter object
// hDll: [in] handle returned by LoadEasyPDFPrinterDLL
// returns a new BclPrinter pointer. Result must be deleted using pPrinter->Dispose(pPrinter);
static BclPrinter* CreatePrinter(HMODULE hDll)
{
   if(hDll)
   {
      typedef BclPrinter* (*BclNewPrinterPtr)(const BclLoaderSettings*);
      BclNewPrinterPtr ptrBclNewPrinter = (BclNewPrinterPtr)GetProcAddress(hDll, "BclNewPrinter");
      return ptrBclNewPrinter(NULL);
   }
   else
      return NULL;
}

// Create a new BclPDFProcessor object
// hDll: [in] handle returned by LoadEasyPDFProcessorDLL
// returns a new BclPDFProcessor pointer. Do not delete the resulting pointer in any way, just unload the DLL.
static const BclPDFProcessor* GetPDFProcessor(HMODULE hDll)
{
   if(hDll)
   {
      typedef const BclPDFProcessor* (*BclGetPDFProcessorPtr)();
      BclGetPDFProcessorPtr ptrBclGetPDFProcessor = (BclGetPDFProcessorPtr)GetProcAddress(hDll, "BclGetPDFProcessor");
      return ptrBclGetPDFProcessor();
   }
   else
      return NULL;
}

// Create a new BclPDFConverter object
// hDll: [in] handle returned by LoadEasyPDFConverterDLL
// returns a new BclPDFConverter pointer. Result must be deleted using pPDFConverter->Dispose(pPDFConverter);
static BclPDFConverter* CreatePDFConverter(HMODULE hDll)
{
   if(hDll)
   {
      typedef BclPDFConverter* (*BclNewPDFConverterPtr)(const BclLoaderSettings*);
      BclNewPDFConverterPtr ptrBclNewPDFConverter = (BclNewPDFConverterPtr)GetProcAddress(hDll, "BclNewPDFConverter");
      return ptrBclNewPDFConverter(NULL);
   }
   else
      return NULL;
}

Loading the DLLs

Depending on which SDK you are planning to use, call LoadEasyPDFPrinterDLL, LoadEasyPDFProcessorDLL or LoadEasyPDFConverterDLL:

HMODULE hPrinterDll = LoadEasyPDFPrinterDLL();
HMODULE hProcessorDll = LoadEasyPDFProcessorDLL();
HMODULE hConverterDll = LoadEasyPDFConverterDLL();

You must hold on to your hDll variables all the way until you no longer need to use easyPDF SDK, at which point you should unload the DLLs:

if(hPrinterDll)
   FreeLibrary(hPrinterDll);
if(hProcessorDll)
   FreeLibrary(hProcessorDll);
if(hConverterDll)
   FreeLibrary(hConverterDll);

Note that Windows automatically unloads all DLLs when your application exits. However, it is still preferred to manually unload easyPDF.

It is critical that you dispose all SDK objects before unloading the DLL.

You may choose to load easyPDF when your application starts, and keep it loaded for the entire time. Alternatively, you could load and unload easyPDF on-demand. It depends how often you are going to call easyPDF functions.

In the next few topics, we are going to discuss each individual SDK separately.