Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / Python

Compiling MuPDF DLL to Render and Edit PDF Documents

Rate me:
Please Sign up or sign in to vote.
4.71/5 (28 votes)
27 Apr 2020CPOL10 min read 76K   4K   71   43
MuPDF is an open-sourced, high performance PDF rendering and editing engine written in C. This article describes how to compile its source code to a DLL for use in other programming languages.
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.
Note about the download:

The download contains a pre-compiled MuPDF DLL (versioned 1.19) 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 repository on GitHub to have all code files you need and get started with the MuPDF.sln solution file.

Note about SumatraPDF:

A previously written article discussed the possibility of getting a DLL file out of the SumatraPDF project, which utilized MuPDF very much. By compiling the SumatraPDF project with Visual Studio 2019, it is very easily to get a MuPDF DLL file named libmupdf.dll.

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.

  1. Visual Studio 2019 with the C++ desktop development payload.
  2. Windows 10 SDK.
  3. (Optional, but recommended) Python to extract function names to a definition file for the compilation of the DLL file.
  4. 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.

  1. source: the C code files
  2. include: the header files
  3. thirdparty: the code files of related open-source projects
  4. platform: projects for code compilation
  5. resources: resources (fonts, character maps, color profiles, PDF names, etc.) used by the engine
  6. 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.

Note:

I suggest you make a copy of mupdf.sln and work on that copy later.

Always avoid modifying 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 MuPDF project.

Open that solution file, you will see more than 10 projects loaded.

The most important projects about compiling a DLL file are listed below:

  1. libmupdf: The project to compile a static library file, libmupdf.lib, which will be used to compile the DLL file
  2. libresources: The project to handle resources, used by libmupdf
  3. libthirdparty: The related open-source projects, used by libmupdf
  4. 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

Before MuPDF 1.17, I used Windows 7 SDK to compile the source code and the project files needed to be upgraded in order to be compiled successfully. From MuPDF 1.17 on, Windows 10 SDK was used and Visual Studio 2019 became the officially supported compiler. We could compile them with Visual Studio 2019 without any problem.

About missing code files: If you download the source code, you have to search the web and download all needed thirdparty source code files. So, it is recommended to clone the project with Visual Studio rather then downloading them.

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.

Tip:

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:

  1. Create a new project to output a DLL file.
  2. Reference related static library files in that project.
  3. Define functions being exposed in the DLL file.

Setting Up the DLL Project

To create a DLL file, we create a new C project in the MuPDF solution. I simply named it MuPDFLib in my solution.

Modify the project as the following list by selecting the MuPDFLib project we created above and clicking the "Project" menu and selecting the "Properties" command:

  1. Select All Configurations and All Platforms.
  2. In the Platform Toolset, use the Visual Studio 2019 (v142).
  3. Change the SDK version to 10 if it isn't.
  4. Change the Configuration to Dynamic Library (.dll).
  5. 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).
  6. Click OK button to close the project properties dialog.

Image 1

Image 2

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 checkboxes besides libmupdf, libresources and libthirdparty as the following picture shows.

Image 3

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.

Functions in 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 MuPDF.

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.

Note:

You may encounter a few LNK2001 errors at compilation indicating that certain functions were not resolved. Simply delete those functions from the automatically generated def file and proceed.

If you don't have Python and you don't want to install it, you may have to manually compose 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:

Image 4

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:

C++
/*
    Choose which fonts to include.
    By default we include the base 14 PDF fonts,
    DroidSansFallback from Android for CJK, and
    Charis SIL from SIL for epub/html.
    Enable the following defines to AVOID including
    unwanted fonts.
*/
/* To avoid all noto fonts except CJK, enable: */
/* #define TOFU */

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.

WARNING:

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 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 <different options>.

Image 5

Recompile the MuPDFLib project and check out the size of the DLL file. It should be much smaller.

Image 6

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

As the MuPDF project revolves, the source code may get changed.

Here's a short summary on keeping synchronized with the MuPDF project.

  1. 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.
    1. When updating the source code, merge the GitHub source into your repository.
    2. Source code conflicts will occur, since if you have modified the libmupdf project in the above procedure to shrink the size of the DLL. We have to solve the conflicts by merging the source code. Use the Source (the official code) when merging.
    3. Don't forget to update the submodules by right clicking updated submodules in the Changes pane of the Team Explorer and execute the corresponding commands, otherwise your project might not compile. Use the Source when resolving any submodule conflicts.
  2. Regenerate the def file for DLL exporting by executing the gen_libmupdf.def.py script if necessary.
  3. Tweak the libmupdf project to shrink the output DLL file by defining font related preprocessor definitions if you want.
  4. Recompile the MuPDFLib project and get the DLL file.
  5. Strip inexisting functions in the def file if you encounter LNK2001 errors.
  6. 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.
  7. Change your source code to adapt to the new MuPDF project API if it changes. It is essential when the version of MuPDF changes.

History

  1. Initial publication in November, 2017
  2. Updated source code in the GitHub fork, and fixed typos in font resource section.
  3. Updated source code in the GitHub fork, recompiled the DLL, updated article to reflect the latest source code changes on November 24th, 2018
  4. Updated source code in the GitHub fork, recompiled the DLL, updated article to add more details to keeping sync with the MuPDF project and reflect the latest source code changes on July 18th, 2019
  5. Updated source code in the GitHub fork to MuPDF 1.16, recompiled the DLL, fixed P/Invoke calling convention issues in demo project on Aug 1st, 2019
  6. Revised the article and updated source code in the GitHub fork to MuPDF 1.17rc, recompiled the DLL on April 28th, 2020

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
China China
I am now programming applications for the Internet of Things.

Comments and Discussions

 
News"Unable to make article available." Pin
wmjordan26-Jan-22 20:10
professionalwmjordan26-Jan-22 20:10 
GeneralRe: "Unable to make article available." Pin
Pedro Gil Valero14-Jun-22 3:58
Pedro Gil Valero14-Jun-22 3:58 
QuestionMuPDF 1.19 Pin
Pedro Gil Valero1-Oct-21 4:56
Pedro Gil Valero1-Oct-21 4:56 
AnswerRe: MuPDF 1.19 Pin
wmjordan1-Oct-21 16:50
professionalwmjordan1-Oct-21 16:50 
AnswerRe: MuPDF 1.19 Pin
wmjordan7-Oct-21 16:45
professionalwmjordan7-Oct-21 16:45 
I've updated the repository and compilation.
Please see here:
Release Version 1.19 · wmjordan/SharpMuPDF · GitHub
GeneralRe: MuPDF 1.19 Pin
Pedro Gil Valero8-Oct-21 2:19
Pedro Gil Valero8-Oct-21 2:19 
QuestionMuPDF 1.18 Pin
Pedro Gil Valero10-Oct-20 5:19
Pedro Gil Valero10-Oct-20 5:19 
AnswerRe: MuPDF 1.18 Pin
wmjordan20-Nov-20 13:25
professionalwmjordan20-Nov-20 13:25 
GeneralRe: MuPDF 1.18 Pin
Pedro Gil Valero21-Nov-20 3:57
Pedro Gil Valero21-Nov-20 3:57 
GeneralRe: MuPDF 1.18 Pin
wmjordan27-Nov-20 20:16
professionalwmjordan27-Nov-20 20:16 
GeneralRe: MuPDF 1.18 Pin
Pedro Gil Valero28-Nov-20 1:33
Pedro Gil Valero28-Nov-20 1:33 
GeneralRe: MuPDF 1.18 Pin
wmjordan28-Nov-20 15:52
professionalwmjordan28-Nov-20 15:52 
GeneralRe: MuPDF 1.18 Pin
Pedro Gil Valero28-Nov-20 23:08
Pedro Gil Valero28-Nov-20 23:08 
GeneralRe: MuPDF 1.18 Pin
wmjordan24-Dec-20 1:26
professionalwmjordan24-Dec-20 1:26 
QuestionDownload Pin
Pedro Gil Valero29-Apr-20 6:41
Pedro Gil Valero29-Apr-20 6:41 
AnswerRe: Download [has been fixed now] Pin
wmjordan3-May-20 23:12
professionalwmjordan3-May-20 23:12 
GeneralRe: Download [has been fixed now] Pin
Pedro Gil Valero6-May-20 8:35
Pedro Gil Valero6-May-20 8:35 
GeneralRe: Download [has been fixed now] Pin
wmjordan6-May-20 14:22
professionalwmjordan6-May-20 14:22 
GeneralRe: Download [has been fixed now] Pin
wmjordan10-May-20 21:15
professionalwmjordan10-May-20 21:15 
GeneralRe: Download [has been fixed now] Pin
Pedro Gil Valero11-May-20 8:26
Pedro Gil Valero11-May-20 8:26 
GeneralMy vote of 5 Pin
Member 1480978723-Apr-20 22:27
Member 1480978723-Apr-20 22:27 
QuestionBuild MuPDF for Android Pin
Mohamad7715-Mar-20 20:56
Mohamad7715-Mar-20 20:56 
AnswerRe: Build MuPDF for Android Pin
wmjordan24-Apr-20 23:25
professionalwmjordan24-Apr-20 23:25 
Questionslow dll Pin
nadmaga19-Jan-20 3:21
nadmaga19-Jan-20 3:21 
AnswerRe: slow dll Pin
wmjordan14-Feb-20 15:13
professionalwmjordan14-Feb-20 15:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.