At our math website we publish printable PDF worksheets for school children. We’ve just started publishing crosswords, while relatively easy to create, they require much work to make them into tasks.
A workflow consists of multiple, repetitive tasks, which could be automated. And that’s what I’m doing with LibreOffice. I’m using LibreOffice as it’s more updated than OpenOffice. Even though they have a lot in common, LibreOffice just feels more right for C++ code than OpenOffice.
This post is the first in a series of LibreOffice C++ tutorials on how to integrate and use LibreOffice with C++.
The first step in integrating LibreOffice into C++, is having both the LibreOffice suite installed and the SDK. I’ll be covering Windows in this guide, as it’s more difficult to get started with than on various Linux distributions.
Head over to https://www.libreoffice.org/download/libreoffice-fresh/ and download the latest release and SDK. Both should be available at that page.
Contrary to regular C++ libraries, the LibreOffice SDK doesn’t come with all headers. In fact, most of the headers have to be generated by a tool called
cppumaker. It’s difficult tool to get started with, as it have some requirements and assumptions whose are not very well documented by the program itself.
Most issues can be solved by looking at the error messages, some searching online and some experimenting. Here I’ll outline most of the errors I encountered.
Cppumaker works by reading some database files, and then generates C++ types from those database files. Those database files comes with the LibreOffice suite and are placed a couple of places in the installation folder.
The bridge between a language and LibreOffice itself is called UNO.
As most people, I don’t like to work directly with system wide files when developing and experimenting with things just like this. Sadly
cppumaker sort of requires to be able to place files directly in the installation folder to the SDK.
We’re still going to create a staging directory, just for the extra challenge.
Create a staging directory somewhere. Where is not important. Create a script called
make_cpp_types.bat in that folder. The output directory
out doesn’t have to exist. It will be created automatically by cppumaker.
Most of the time I make scripts when doing complex operations on the Windows command line. This is no exception. It’s easier to just restart the script, than to manually enter PATH environment variables every time you accidentally wipe the
PATH variable or close the command line window.
With the LibreOffice SDK, there are a couple of items in various folders. The program
cppumaker is in one folder, while it’s dependencies are in an other directory, while the RDB are in some other folders. It’s a mess to fiddle with manually on the command line.
Here is the beginning of a batch script gathering the pieces together.
rem Start path set STARTDIR=%cd% rem Libre paths. May have to be adjusted set LIBRE=C:\Program Files (x86)\LibreOffice 5 set LIBREPROGRAM=%LIBRE%\program set LIBRESDK=%LIBRE%\sdk\bin set PATH=%LIBREPROGRAM%;%LIBRESDK%;%PATH%
At this point, all we’ve done is to modify the PATH variable to contain the path to cppumaker and it’s dependencies. This is to be able to run cppumaker.
Next up is making variables for the three databases to generate types from. Those are types.rdb, offapi.rdb and oovbaapi.rdb.
set STAGE=%STARTDIR%\out set TYPES=%LIBREPROGRAM%\types.rdb set OOVBAAPI=%LIBREPROGRAM%\types\oovbaapi.rdb set OFFAPI=%LIBREPROGRAM%\types\offapi.rdb
The final command is calling cppumaker with the correct parameters. It is very picky about the parameters, so be careful.
With the variables from above, calling
cppumaker will look like this.
cppumaker -O "%STAGE%" "%TYPES%" "%OOVBAAPI%" "%OFFAPI%" pause
When the script is done running, there should be a bunch of other files and folders. Copy those files back to the SDK directory, keeping the same directory structure, or adjust the script so the staging directory points to the SDK include directory and run the script as administator.
For the lazy, the stage directory for non-staging is:
set STAGE=C:\Program Files (x86)\LibreOffice 5\sdk\include
The final script should look something like this, adjusted for your paths.
rem Libre paths. May have to be adjusted set LIBRE=C:\Program Files (x86)\LibreOffice 5 set LIBREPROGRAM=%LIBRE%\program set LIBRESDK=%LIBRE%\sdk\bin set PATH=%LIBREPROGRAM%;%LIBRESDK%;%PATH% set STAGE=%STARTDIR%\out set TYPES=%LIBREPROGRAM%\types.rdb set OOVBAAPI=%LIBREPROGRAM%\types\oovbaapi.rdb set OFFAPI=%LIBREPROGRAM%\types\offapi.rdb rem Alternate STAGE directory, uncomment and run as Administrator rem to generate headers into the LibreOffice SDK incldue directory rem set STAGE=C:\Program Files (x86)\LibreOffice 5\sdk\include cppumaker -O "%STAGE%" "%TYPES%" "%OOVBAAPI%" "%OFFAPI%" pause
It’s not trivially easy to make this program generate the headers, and there are many pitfalls getting it just right. And it has to be just right.
If you get messageboxes saying that either
unoidllo.dll are missing, the PATH variable isn’t set properly. It has to contain the LibreOffice program directory for the DLLs to be found.
ERROR: No such file is because there is a slash at the end of the output path. Remove the slash and try again.
rem Wrong STAGE set STAGE=%STARTDIR%\out\ rem Correct STAGE (notice the slash at the end) set STAGE=%STARTDIR%\out
You are trying to write to the installation directory, for which you need administrator privileges. Run the script as administrator and try again.
types.rdb is not provided on the command line, only the file
offapi.rdb. Provide both and try again.
Same as above, but only with
oovbaapi.rdb. The file
types.rdb must be provided on the command line to
Up until now the article have been about just getting the headers to work. Actually using the headers is something else. But before that, Visual Studio must know where to locate the headers.
C:\Program Files (x86)\LibreOffice 5\sdk\include to Additional Include Directories.
If properly done, then this code should compile.
#include <sal/main.h> #include <cppuhelper/bootstrap.hxx> #include <osl/file.hxx> #include <osl/process.h> #include <rtl/process.h> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/bridge/XUnoUrlResolver.hpp> #include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/frame/XComponentLoader.hpp> #include <com/sun/star/lang/XMultiComponentFactory.hpp> #include <com/sun/star/registry/XSimpleRegistry.hpp> #include <string.h> using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::beans; using namespace com::sun::star::bridge; using namespace com::sun::star::frame; using namespace com::sun::star::registry;
If anything is missing, the compiler will tell you about it.
This concludes this article about getting started with integrating LibreOffice SDK into C++ and Visual Studio. Next is about actually doing integration work and what errors you may encounter in the process.