Note about the download:
The download contains a pre-compiled MuPDF DLL (versioned 1.14) with a simple C# demo project which utilizes functionalities in the DLL to convert PDF documents into image files.
As an alternative to downloading the above files, you can also clone my fork on GitHub to have all code files you need and get started with the MuPDF Sharp.sln file in the platform/win32 folder.
MuPDF is an open-sourced, high performance PDF rendering and editing engine written in C. However, the compilation results of its source code do not contain a DLL for use from other languages, such as C#, Visual BASIC, etc. This article will show you the way to compile the source code to a dynamic link library.
What We Need
The source code of MuPDF can be downloaded from its official website, or from the mirror on GitHub.com. The following list contains all we need to compile the MuPDF source code.
- Visual Studio 2017 with the C++ desktop development payload and the latest update.
- Windows SDK from 7.0 up. The Windows 10 SDK might also work as well, but I have not tested it.
- (Optional, but recommended) Python to extract function names to a definition file for the compilation of the DLL file.
- About 1 GB free bytes on your hard drive for code compilation.
Compiling the Source Code
The source code of MuPDF is separated to several directories containing thousands of code files.
- source: the C code files
- include: the header files
- thirdparty: the code files of related open-source projects
- platform: projects for code compilation
- resources: resources (fonts, character maps, color profiles, PDF names, etc.) used by the engine
- scripts: some code files which help compilation
The Related Project Files
Navigate to the platform/win32 directory, you will see quite a few C project files and a solution file named mupdf.sln.
I suggest you make a copy of mupdf.sln and work on that copy later.
NEVER modify the source code unless you know what you are doing and want to participate in contributing to the
MuPDF project. Have you modified the source code, you may have trouble merging the source code later, when you want to keep synchronized with the
Open that solution file, copy with Visual Studio 2017, you will be prompted to upgrade the solution and the projects. Do it. Afterwards, you will see more than 10 projects loaded.
The most important projects about compiling a DLL file are listed below:
libmupdf: The project to compile a static library file, libmupdf.lib, which will be used to compile the DLL file
libresources: The project to handle resources, used by
libthirdparty: The related open-source projects, used by
bin2coff: The automation project which generates font resource files for the other projects.
If your goal is to compile the MuPDF DLL file only, the rest of the projects in the solution are ignorable. So you can safely unload them or remove them from the solution.
The projects must be compiled in the reverse order as they are listed above, from bin2coff to libmupdf, for the dependencies among them.
Compiling Source Projects
For the above 4 projects, we begin with the
Check the Configuration and Platform drop down list on the Property Pages dialog. The first one contains only
Release and the later one contains only
Win32. So there's no need to change them.
Optional: Find the Windows SDK version property and change it to
7.0. If you are targeting Windows 8 up and have the Windows 8.1 SDK in Visual Studio installed on your machine, you can skip this procedure. I did this because I never targeted my projects to Windows 8.
You may also change the Platform Toolset property to Visual Studio 2017 - Windows XP (v141_xp).
Click the OK button to close the dialog.
Compile the project. Things should go well.
Open the properties dialog for the next essential project file: libthirdparty.
Check the Configuration dropdown list, and you can see that there are quite a few items, such as the Platform dropdown list. For convenience, we select
All Configurations from the Configuration dropdown list and
All Platforms from the Platform dropdown list, so our changes will be applied to all compilation configurations and platforms.
Change the Windows SDK Version and the Platform Toolset properties when needed.
Repeat the above procedure and compile rest of the projects one by one. Finally, you will get a static library file named libmupdf.lib, in the output folder.
The SDK version you choose here may affect the compatibility of the DLL. If you have used the Windows 10 SDK here, your DLL may not run on earlier versions of Windows systems.
Creating the DLL
We are very close to what we want now.
To obtain a dynamic library file out of the static library file, we need to create another project.
The reason why I don't modify the libmupdf project to make it generate a DLL file is that I want to keep the other projects referencing libmupdf in the solution still be compilable, and easier the process when we synchronize the source code files later when the MuPDF source code gets updated.
To create the DLL file, we will have to do three things:
- Create a new project to output a DLL file.
- Reference related static library files in that project.
- Define functions being exposed in the DLL file.
Setting Up the DLL Project
To create a DLL file, we create a new project in the
MuPDF solution. I simply named it
MuPDFLib in my solution.
Modify the project as the following list by right clicking the project file in the solution explorer and selecting the "Properties" command:
- Select All Configurations and All Platforms.
- Change the SDK version to 7.0 (or leave it along, if you are targeting Windows 8 up and installed the Windows 8.1 SDK in Visual Studio installation)
- Change the Configuration to Dynamic Library (.dll).
- Remove the CLR support (optional).
- Switch to the Linker/Input section in the project properties dialog, and set the Module Definition File property to "libmupdf.def" (we will generate this file later).
- Click OK button to close the project properties dialog.
Referencing Related Static Library Files
Right click the References in the
MuPDFLib project in the solution explorer. From the popped-up context menu, select the Add Reference command, which will open a dialog. In that dialog, check the checkbox besides libmupdf, libresources and libthirdparty.
Creating the Definition File of DLL Functions
The above setting will not yet compile a workable DLL file out of the
MuPDF source code, unless we create the missing
libmupdf.def function definition file referenced by the project. A definition file is a list which defines what functions can be exposed out of the compiled DLL file.
MuPDF project are placed in header files in the include folder. However, since the project contains quite some scores of header files, it is not a funny task to extract those function names manually.
Fortunately, the developers of SumatraPDF (a PDF viewer application which based on
MuPDF) created a Python script to generate that def file for us. You can copy the script file from the repository of SumatraPDF and place it in the scripts folder where you store the source code of
The script needs some modifications to reflect the latest changes of MuPDF. I uploaded my own version to my GitHub repository. If you already have Python 2.7 installed on your computer, place the script files, gen_libmupdf.def.py, util.py into the scripts folder, double click gen_libmupdf.def.py and it will generate the def file in the platform/win32 folder.
Having the def file generated, we can start compiling the DLL file.
You may encounter a few
LNK2001 errors at compilation indicating that certain functions were not resolved. Simply delete those functions from the def file and proceed.
If you don't have Python and you don't want to install it, you may have to manually edit the def file with a code editor, or program your own application to generate the def file.
I suggest you use the Python script to do the dirty job for you.
Eventually, you will obtain the DLL file in the platform/win32/Release (or platform/win32/Debug, etc.) folder. Where you can find the DLL file depends on your compilation configuration.
Examining Exported Functions
So far, we have already obtained the DLL file of the
MuPDF engine. You can examine whether the functions have been exported by the DLL file with the DLL Export Viewer, a small utility developed by nirsoft.net.
The exported functions in DLL Export Viewer may look like the following picture:
Shrinking the DLL File by Excluding Unwanted Fonts
Some of you may notice that the compiled DLL is a little bit large, up to about 34 megabytes. The reason why it takes so much space is that it has embedded many fonts for international character support. We can shrink its size to about 8 megabytes by excluding those font files from the compiled DLL.
To make the customized DLL, open the
libmupdf project, expand the !include/fitz folder and click the config.h file. You can see a lot of comments and definition directives there. Scroll down to the comment with a text "
Choose which fonts to include", and below, there are some commented lines, like the following:
Like it said, by defining
TOFU;TOFU_CJK_EXT, you will exclude several huge noto fonts and CJK extension fonts from the DLL file, and reduce the output size from 34 megabytes to about 8 megabytes.
Be careful when following the instruction in the source code:
Enable the following defines to AVOID including unwanted fonts.
If you modify the source code by uncommenting the lines below the above line, you will encounter source code conflicts later when you synchronize with the updated source code.
I advice you that DO NOT modify the source code; DO modify the
libmupdf project properties and add definitions to the Preprocessor Definitions property as the screenshot shows. Notice the "
;" before "
TOFU" which separates definitions from
MuPDFLib project and check out the size of the DLL file. It should be much smaller.
Consuming Functions in the DLL File
I am not going to write too much in this article on how to consume the functions in the DLL. For C# programmers, you may use the Platform Invoking technology. Previously, I wrote an article P/Invoking MuPDF library to render PDF documents. You may refer to it by clicking the link above.
The download link at the top of this article has a sample project, which demonstrates how to use P/Invoke from C# to consume functions in the compiled DLL file.
Keeping Synchronized with the MuPDF Project
MuPDF project revolves, the source code may get changed.
Here's a short summary on keeping synchronized with the
- If your source code is cloned from GitHub, update it; otherwise you may download the source code from the official website and overwrite the existing code files. I prefer the former approach since it downloads less bytes at update.
- When updating the source code, merge the GitHub source into your repository.
- If source code conflicts occur, use the Source.
- Don't forget to update the submodules, otherwise your project might not compile.
- Open the platform/win32 folder, compare the file modification dates of each project file with the upgraded ones.
- Open Visual Studio.
- If a certain related projects are changed, DO remove those projects from the Solution Explorer in Visual Studio; DO NOT remove the vcxproj files from the Windows Explorer. If no projects have been changed, skip to step 8 to recompile the DLL file from the source code.
- Add the updated vcproj files back to the solution via Solution Explorer by adding the existing project and let Visual Studio update them and generate the corresponding vcxproj files, overwriting the old ones.
- Repeat the steps in Compiling source projects section in this article to change the Windows SDK, code references, and other project properties.
- Add back project references to
MuPDFLib project--the project that compiles the DLL file.
- Regenerate the def file for DLL exporting if necessary.
- Tweak the
libmupdf project to shrink the output DLL file by defining font related preprocessor definitions if you want.
- Recompile the
MuPDFLib project and get the DLL file.
- Check the commit history of
MuPDF project and see whether header files (*.h files) in the project have been changed. When changes have occurred, find out what has been changed by comparing commission histories.
- Change your source code to adapt to the new
MuPDF project API if it changes.
- Initial publication in November, 2017
- Updated source code in the GitHub fork, and fixed typos in font resource section.
- Updated source code in the GitHub fork, recompiled the DLL, updated article to reflect the latest source code changes on November 24th, 2018