Build C++ Integrations with LibreOffice SDK
This guide outlines how developers can leverage the LibreOffice Software Development Kit (SDK) to create high-performance C++ integrations. By utilizing the Universal Network Objects (UNO) component model, developers can automate document generation, convert file formats, and extend LibreOffice features programmatically. The following sections cover environment setup, core UNO architecture, bootstrapping a connection, document manipulation, and compilation best practices.
1. Setting Up the Environment
To begin development, install both the LibreOffice application and the LibreOffice SDK matching your target operating system. The SDK provides the required header files, libraries, binary tools, and sample code.
After installation, initialize the SDK build environment using the
provided setup script: * Linux/macOS: Run
source <sdk_path>/setsdkenv_unix.sh *
Windows: Execute
<sdk_path>\setsdkenv_windows.bat
This configuration script configures paths for the C++ compiler (such
as GCC, Clang, or MSVC), the LibreOffice runtime, and SDK tools like
cppumaker.
2. Understanding the UNO Architecture
LibreOffice exposes its capabilities through Universal Network Objects (UNO), a language-independent component architecture. In C++, developers interact with UNO objects via interfaces defined in UNO IDL (Interface Definition Language).
Key UNO concepts include: *
Reference<T>: A smart pointer
managing reference counting for UNO interfaces. * Component
Context (XComponentContext): The central registry
providing access to services and singletons. * Service Manager
(XMultiComponentFactory): Creates instances of UNO
services.
3. Bootstrapping and Connecting
To control LibreOffice from a standalone C++ process, you must
initialize the UNO runtime and obtain the initial component context. The
cppuhelper library provides helper functions to bootstrap a
connection to a local or remote LibreOffice installation.
#include <sal/main.h>
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/frame/Desktop.hpp>
using namespace com::sun::star;
int main(int argc, char* argv[]) {
// Initialize the UNO component context
uno::Reference<uno::XComponentContext> xContext = cppuhelper::bootstrap();
// Retrieve the Service Manager
uno::Reference<lang::XMultiComponentFactory> xServiceManager =
xContext->getServiceManager();
// Instantiate the Desktop service to interact with documents
uno::Reference<frame::XComponentLoader> xComponentLoader(
frame::Desktop::create(xContext), uno::UNO_QUERY_THROW);
return 0;
}4. Opening and Manipulating Documents
Once the XComponentLoader interface is initialized, you
can load existing files or create new documents using the
loadComponentFromURL method. LibreOffice requires file
paths formatted as standard URIs (e.g.,
file:///path/to/document.odt).
Common operations include: * Creating a Blank
Document: Pass private:factory/swriter (Writer) or
private:factory/scalc (Calc) to
loadComponentFromURL. * Modifying Content:
Query interfaces such as text::XTextDocument to access the
document body, cursors, and formatting properties. *
Exporting/Saving: Query the
frame::XStorable interface to invoke
storeToURL or storeAsURL with filter options
for PDF export or format conversion.
5. Type Generation and Linking
LibreOffice interfaces are distributed as binary type libraries
(.rdb files). C++ programs require corresponding header
files generated by the cppumaker tool.
During the build process: 1. Run cppumaker against the
offapi.rdb and types.rdb registries to
generate C++ header representations under an include/
directory. 2. Include the generated headers for the specific interfaces
you use (e.g., com/sun/star/text/XTextDocument.hpp). 3.
Link your application against the core UNO runtime libraries:
libuno_sal, libuno_cppu,
libuno_cppuhelpergcc3 (or MSVC equivalent), and
libuno_salhelper.
6. Error Handling and Resource Management
All UNO API calls can throw
com::sun::star::uno::Exception or derived exceptions such
as RuntimeException and
IllegalArgumentException. Wrap API interactions inside
try-catch blocks to handle IPC failures, missing filters,
or invalid file URLs cleanly. Use uno::Reference to
automatically manage object lifecycles and avoid memory leaks. When
closing documents, explicitly invoke close(sal_True) on the
util::XCloseable interface to ensure background locks are
released.