Skip to content

Adding Pure Data external libraries to your project

Dan Wilcox edited this page Sep 30, 2016 · 5 revisions

libpd only includes the standard set of Pure Data objects as found in the "Vanilla" version of Pd. If you wish to include an external library from Pd-extended, etc you need to include the source files in your project and call the library setup function after initializing libpd in order to load the lib.

Adding external source files

The source files for externals included with Pd-extended can be found in the Pure Data Git repositories: http://git.puredata.info/cgit. Other externs may be found elsewhere, including on GitHub.

For example, if we want to include the zexy external in your project, first download the sources files from the Git repository (make sure you have git installed):

git clone https://git.puredata.info/cgit/svn2git/libraries/zexy.git

Once cloned, the zexy sources are in zexy/src/. Copy the .h and .c files into your project folder. In my case I create an externals folder in the src folder of my project, something like myProject/src/externals/zexy. Then add these files to your project.

Note: Some libraries may require external libraries of their own and/or special compile time definitions. Make sure you read the build documentation on the external and include these with your project.

Calling the external setup function

In order for libpd to use an external library, the library has to register itself on startup. This is accomplished by calling the library's setup function which is named after the library followed by a "_setup" suffix: "library_setup()". The zexy setup function is simply "zexy_setup()". Call this setup function after initializing libpd:

// init libpd
libpd_init();
    
// load libs
zexy_setup();

If all goes well, you should see some sort of print from the library as it initializes:

[zexy] part of zexy-2.2.3 (compiled: Aug  7 2011)
	Copyright (l) 1999-2008 IOhannes m zmölnig, forum::für::umläute & IEM
[&&~] part of zexy-2.2.3 (compiled: Aug  7 2011)
	Copyright (l) 1999-2008 IOhannes m zmölnig, forum::für::umläute & IEM
[.] part of zexy-2.2.3 (compiled: Aug  7 2011)
	Copyright (l) 1999-2008 IOhannes m zmölnig, forum::für::umläute & IEM
...

Forward declaring the external setup function

Most Pd externals are designed around being dynamic libraries and are not provided with .h header files which include the function declarations. Long story short, if the external's source files only declare the library setup() function in a .c implementation file, you will need to declare the function before you can use it.

In C, this might look like:

#include "z_libpd.h"

// forward declare external setup functions
void zexy_setup();

int main() {

    // init libpd
    libpd_init();
    
    // load libs
    zexy_setup();

    ...
}

Note: Do not include/import the .c file or you will end up with duplicate symbol linker errors.

C++

Some pure C libraries are not written with explicit C++ support in mind and, for arcane reasons best not delved into here, the C++ compiler will not be able to find the library's setup function. This is the case with zexy and the compiler error looks like this:

'zexy_setup' was not declared in this scope

In order for the C++ compiler to find the function, you need to add your own declaration. This can be done in your app .cpp file, a project header file, etc. Declare the "zexy_setup()" function using a special syntax:

#include "z_libpd.h"

// forward declare external C setup function
extern "C" {
    void zexy_setup();
}

int main() {

    // init libpd
    libpd_init();
    
    // load libs
    zexy_setup();
    
    ...
}

The extern "C" keywords tell the compiler to look for a pure C function, not a C++ function. Add a setup function declaration for any other externals that need it.

Obj-C

As Obj-C is a superset of C, a plain forward declaration will work in a .m/.mm implementation file:

#import "PdBase.h"
#import "PdAudioController.h"

// forward declare external setup functions
void zexy_setup();

@implementation YourClass

// whatever method you use to init libpd
- (void)setup {

    // Configure a typical audio session with 2 output channels
    self.audioController = [[PdAudioController alloc] init];
    PdAudioStatus status = [self.audioController configurePlaybackWithSampleRate:44100    

    // load libs
    zexy_setup();

    ...
}

...

Adding files to an Xcode project

Files are typically added to an Xcode project by dragging the files/folders from the Finder into the Xcode project tree. Make sure that when you drag files into Xcode, you check the checkbox next to your project's build target. If not, then those files are added but not added to the target's build and the external will not be built when you build the target. If you're not sure, check if the source files are listed in the "Compile Sources" of the "Build Phases" section of the project.

Swift

In Swift, you will need to create a bridging header file where you can declare the function:

#ifndef MyProject_Bridging_Header_h
#define MyProject_Bridging_Header_h

// forward declare external setup functions
void zexy_setup();

...

#endif /* MyProject_Bridging_Header_h */

Then in Swift, you can now call the declared function after initing libpd:

zexy_setup()

Also, see the Adding files to an Xcode project in the Obj-C section above.

Java / Python / C#, etc

As Java, Python & C# libpd modules are built from C, you will probably need to include the external sources and build a custom wrapper in order to call the library setup functions directly.

Feel free to expand this section.

External library licensing on iOS

Apple's iOS and App Store policies forbid dynamically linking libraries. As such, you cannot include any GPL licensed externals as the GPL expressly requires dynamic linking. Submitting an app using a GPL library is in violation of the GPL and will most likely result in your app being rejected from distribution in the App Store.

GPL patches, however, are not in violation of GPL distribution policies and can be included. They are not compiled into an application binary and can be replaced by the user.

You can’t perform that action at this time.