Developing cross-platform plugins for BrainVoyager QX

Hester Breman, Pim Pullens and Joost Mulders Brain Innovation B.V.

June 12, 2009 Contents

1 Description 3 1.1 About plugins ...... 3 1.1.1 Terminology ...... 3 1.2 General development process ...... 5 1.2.1 Creating a *.dylib (Mac OS X) ...... 5 1.2.2 Mixing and C++ ...... 5

2 Developing source code 7 2.1 Integrated Development Environments (IDE) ...... 7 2.1.1 Creating a project in Visual Studio ...... 8 2.1.2 Creating a project in ...... 12 2.1.3 Code completion ...... 12 2.2 Using tools and libraries ...... 13 2.2.1 Using Numerical Recipes’ code ...... 13 2.2.2 Using precompiled libraries ...... 13 2.3 Platform differences ...... 14 2.3.1 Swapping ...... 14 2.4 Documentation generation (API) ...... 15 2.4.1 Windows ...... 15 2.4.2 Mac OS X ...... 16

3 Configuration 18 3.1 Introduction ...... 18 3.2 Changing plugin names ...... 18 3.2.1 Windows: Visual Studio ...... 18 3.2.2 Mac OS X: XCode ...... 19

4 Building the plugin 20 4.1 Windows ...... 20 4.2 ...... 20 4.2.1 Using a batch file ...... 20

5 Debugging 22 5.1 Introduction ...... 22 5.1.1 Debugging symbols ...... 22 5.1.2 General problem solving ...... 22 5.2 Debugging on Windows ...... 23 5.2.1 Preparation ...... 23 5.2.2 Setting breakpoints in the code ...... 24 5.3 Run the BrainVoyager QX plugin while debugging ...... 26 5.3.1 Starting the debugging ...... 26 5.3.2 Solving problems ...... 29

1 5.4 Debugging on Mac OS X ...... 30 5.4.1 Solving problems ...... 32

6 Source control 33 6.1 Introduction ...... 33 6.2 Source control on Windows ...... 33 6.3 Source control on Mac OS X ...... 33 6.4 Source control on Linux ...... 33

A Document history 35

2 Chapter 1

Description

1.1 About plugins

It is possible to add your own functionality in C++ code to BrainVoyager QX [1] via the plugin mechanism. The code is added to the execute() function of the *.cpp file (derived from a template file that should be used in order to get the plugin working) and possibly additional files in case the execute() function becomes too large. Also, BrainVoyager QX plugin access header files are provided (via the ’Download’ section of the BrainVoyager website http://www.brainvoyager.com/). These header files contain file format and function definitions. The header files are updated regularly, so take care to use the proper version for your BrainVoyager program.

1.1.1 Terminology The following information about plugins was obtained from information provided online by Microsoft. A dynamic-link library (DLL) is an executable file that acts as a shared library of functions. Dynamic linking provides a way for a process to call a function that is not part of its executable code. The executable code for the function is located in a DLL, which contains one or more functions that are compiled, linked, and stored separately from the processes that use them. DLLs also facilitate the sharing of data and resources. Multiple applications can simultaneously access the contents of a single copy of a DLL in memory. Dynamic linking differs from static linking in that it allows an exe- cutable module (either a .dll or .exe file) to include only the information needed at run time to locate the executable code for a DLL function. In static linking, the linker gets all of the referenced functions from the static link library and places it with your code into your executable. Using dynamic linking instead of static linking offers several advan- tages. DLLs save memory, reduce swapping, save disk space, upgrade easier, provide after-market support, provide a mechanism to extend the MFC [Microsoft Foundation Classes, HB] library classes, support multilanguage programs, and ease the creation of international ver- sions. The following definitions were obtained from Apple documentation.

Executable: Executables are standalone binaries and cannot be linked.

3 Dynamic Library: Dynamic libraries are linked at build time and loaded automat- ically when needed. Bundle: Bundle libraries are loaded explicitly at run time (Mac OS X only). Static Library: Static libraries are linked at build time and loaded at execution time.

Relocatable Object File: Object files are single-module files which are linked at build time.

4 1.2 General development process

1.2.1 Creating a *.dylib (Mac OS X) The process to create a dynamic library (*.dylib) for Mac OS X is depicted in figure 1.1.

Figure 1.1: Creating a dynamic library (*.dylib) on Mac OS X

1.2.2 Mixing C and C++ When using C++ concepts in your C code, including only the headers, for example , and might not suffice to get the code working. One needs to declare using the namespace “standard” (see figure ??).

5 Figure 1.2: When mixing C++ with your C code, it can be necessary to add ‘using namespace std;’

6 Chapter 2

Developing source code

In this chapter are some suggestions provided that might be useful when coding a plugin for BrainVoyager QX.

2.1 Integrated Development Environments (IDE)

Although some prefer to developer their code in a text editor like vi or code editor, and compile the code with a Makefile, it is also possible to use a code development environment that provides editing and compiling functionality. This is called a integrated development environment (IDE). A well-known IDE for Windows is from Microsoft: Visual Studio. Apple provides the IDE XCode. For Linux KDevelop is available. This uses an external compiler, for example the GNU compiler gcc. Cross-platforms alternatives are Code::Blocks (see http://www.codeblocks.org/) and Qt Creator (see http://www.qtsoftware.com/downloads/). Thanks to Michele Rodaro for the Code::Blocks recommendation.

7 2.1.1 Creating a project in Visual Studio When creating a plugin for BrainVoyager QX, one always needs the BrainVoyager Plugin Access functions and the file format files (for example Plugin_VMR_Header.h). Therefore, in Visual Studio, we can start a new project from existing files (see figure 2.1).

Figure 2.1: Step 1 in Visual Studio

8 Select the C++ language (see figure 2.2).

Figure 2.2: Step 2 in Visual Studio

9 Select the directory where the BrainVoyager Plugin Access header files are lo- cated. The Visual Studio project will be created in this folder as well (see figure 2.3).

Figure 2.3: Step 3 in Visual Studio

10 Select the Dynamic Library type of project (see figure 2.4).

Figure 2.4: Step 4 in Visual Studio

11 2.1.2 Creating a project in XCode 2.1.3 Code completion In XCode on Mac OS X, code completion can be performed by CodeSense. Go to the ‘Preferences’ tab of XCode to enable CodeSense. On Windows, you will need an additional tool for Visual Studio to perform autocompletion; the WholeTomato software is well recommended.

12 2.2 Using tools and libraries

2.2.1 Using Numerical Recipes’ code The numerical recipes from Vetterling et al [2] can be used successfully if

1. the function files (*.c or *.cpp) are embedded in the XCode or Visual Studio project; in case of *.c files, the files might need to be renamed to *.cpp 2. the project settings are thus modified that the headers of the numerical recipes functions can be found

3. when using the data structures, take care of the indexing of matrices and arrays (1...n) instead of (0...n-1).

2.2.2 Using precompiled libraries The following section can be relevant when using pre-compiled (scientific) libraries. 1. Copy the *.lib file into C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Lib. In Visual Studio, set the properties of your project as follows: 2. Properties → Linker → Input → additional dependencies → select the *.lib file. 3. Properties → General → Additional Include directories → add the directories where other files of the library are located. 4. Copy the *.dll file(s) into the output directory of your project (ie the place where your nice exe or dll lives).

13 2.3 Platform differences

2.3.1 Swapping Some machines are still big endian, which causes a shuffling of the bytes in each multi-byte data type like short, float, integer and double. An example is the Apple PowerPC. To adapt the data handling to the routines, the headers CFByteOrder.h of the CoreFoundation classes or NS....h of the Cocoa classes can be used. Apple developed a mechanism called universal binary, which runs on both Pow- erPC and Intel Mac machines. When the dynamic library was originally developed for PowerPC but is used on Intel Mac, the translation system “Rosetta” is used to provide necessary adaptations of the plugin.

14 2.4 Documentation generation (API)

When other people are going to use the functions, or just for later, it might be use- ful to write above each function a short explanation of the input parameters, the output values and the goal of the function. If these explanations are written with some attention for the format, they can be automatically collected in a document or HTML pages and resemble the interface to your functions, e.g. an Application ’s Interface (API). Some open-source tools can be downloaded from SourceForge.net, like or doc++. Others are included in the integrated development environments (IDEs) like HeaderDoc in XCode on Mac OS X. The documentation generation usually consists of two steps. In the first step, all documentation fragments are collected; in doc++ for example, this process is called “docify”. Secondly, the documentation is generated from the collected frag- ments; in doc++, this is called “docxx”. Concerning the format, each fragment will need to have a tag for beginning and ending. The beginning is usually a variation on commenting, like /** (for doc++), \*! (for HeaderDoc). Furthermore, tags are used to indicate the input parameters (@param) or version of the function (@version).

2.4.1 Windows On Windows, the tool doc++ or doxygen can be used. See figure 2.5 for an exam- ple of the markup.

Figure 2.5: Example of using tags for documentation generation in doc++

doc++ can be downloaded from SourceForge via http://sourceforge.net/projects/docpp/

15 2.4.2 Mac OS X The functions in the header files of a BrainVoyager QX plugin can be commented so that an Application Programmer’s Interface (API) is easily generated in HTML. On Mac OS X, the command line tool HeaderDoc can be used if the DeveloperTools have been installed. The markup is performed via the tool HeaderDoc from Apple (see http://developer.apple.com/opensource/tools/headerdoc.html). The begin tag is /*! and the end tag */ (see figure 2.6).

Figure 2.6: Example of using tags for documentation generation in HeaderDoc

Run the tool from the command line, typing the filename or a directory (see figure 2.7). The tool GatherHeaderDoc from Apple creates a nice menu for the collection of HTML files. When creating an API for a plugin, it is convenient only to take a selection of header files (*.h), copy these to a new directory and run Header- Doc there. Even more convenient is to use a batch file to run HeaderDoc, in the following fashion: #!/bin/ headerdoc2html /Users///

To get this working on your Mac, do the following:

1. Save the text (with adapted directory names) in an empty XCode file. 2. Give the file execution permissions by typing chmod a + x in the Terminal (the Terminal application can be found in Finder → Applica- tions → Utilities).

3. Execute the batch file by typing ./ in the Terminal.

16 Figure 2.7: HTML API file generated by HeaderDoc

17 Chapter 3

Configuration

3.1 Introduction

In this chapter is described how to configure settings of the Integrated Develop- ment Environment (IDE).

3.2 Changing plugin names

3.2.1 Windows: Visual Studio To change the name of your plugin in Visual Studio 2005, go to ’Project’ → ’Prop- erties’ → ’Configuration Properties’ → ’Linker’ → ’General’ → ’Output file’ (see figure 3.1).

Figure 3.1: Changing the name of the plugin in Visual Studio 2005

18 3.2.2 Mac OS X: XCode (XCode 3.0) Go to XCode menu option “Project” → “Edit Project Settings” and click on the “Build” tab. Change the Product Name in the “Packaging” section (see figure 3.2).

Figure 3.2: Change the name for the plugin in an XCode project

19 Chapter 4

Building the plugin

4.1 Windows

When using Visual Studio, just go to the “Build” menu and select “Build” or “Re- build”. If the plugin is intended for other users as well, take care to build in Release Mode and not in Debug Mode, otherwise the plugin is not recognized by BrainVoy- ager QX. See figure 4.1 for information how to change the build mode.

Figure 4.1: Build in Release mode

4.2 Linux

On Linux, the static header files BVQXPluginInterface.h/cpp might need to be used. In case the files do not build, concatenate the *.cpp files to one file. The approach explained below was proposed and materialized by Jochen Weber.

4.2.1 Using a batch file The text below constitutes a batch file that makes it possible to compile the plugin on Linux (for example SUSE 10.1). To use this, do the following:

1. save the text in an empty file (without markup), for example as ’conccfiles’ 2. give the batch file executive permissions by typing chmod a+x in the bash terminal 3. place the file in the directory of the C++ files

4. execute the batch file by typing

20 The batch file

#!/bin/bash rm -f concatenated.cpp for n in *.c* ; do if [[ "x$n" != "xconcatenated.cpp" ]] ; then echo "#include \"$n\"" >> concatenated.cpp fi done gcc -c -shared -ldl -lpthread -O2 -Wall -DMAKE_PLUGIN -fPIC -o concatenated.o concatenated.cpp --debug v gcc -shared -Wl,-fPIC -fPIC -ldl -lpthread -I. -o $1 concatenated.o

21 Chapter 5

Debugging

5.1 Introduction

5.1.1 Debugging symbols Debugging symbols are additional information compiled into a binary file by a compiler. They enable a developer using a debugger to gain additional informa- tion about the binary, such as the names of variables and routines from the orig- inal source code. The inclusion of debugging symbols can increase the size of a program or library significantly. Additionally, the inclusion of debugging symbols often prevents some compiler optimizations, which in turn could negatively im- pact performance. Debug symbols may also provide more of a glimpse into the source than software developers wish to be made publicly available. For these reasons, debug symbols are usually stripped from the binary before software is released to the general public (from: http://www.wikipedia.org).

5.1.2 General problem solving • Errors when compiling while libraries have been properly included For example map and iterator give errors when using #include etc. Solution: also declare to use namespace standard (see section 1.2.2).

22 5.2 Debugging on Windows

5.2.1 Preparation Project settings Changing the project properties To use debugging in Visual Studio 2005, go to the project properties via ’Project’ and then ’Properties’ or ALT + F7 to change the following configuration settings:

• In tab ’Debugging’, set the Command to the path and name of BrainVoyager QX. • In tab ’Debugging’, set Attach to No. • In tab ’Debugging’, set Merge Environment to Yes (see figure 5.1). • In tab ’C++’, ’General’, set the Debug Information format to Program Database (/ZI) • In tab ’C++’, ’General’, set ’Optimization’ to Disabled (/Od) • In tab ’Linker’, ’Debugging’, set ’Generate Debug Info’ to Yes (/DEBUG). The Generate Program Database file will automatically adapt.

Figure 5.1: Set Merge Environment to Yes

Click the ’Apply’ button and close the dialog.

23 Figure 5.2: Enabling the inclusion of symbols

Adding debugging symbols to the plugin (*.dll) For enabling debugging symbols, see figure 5.2. Go to ’Tools’ and then ’Options’ to change the symbols (see figure 5.2):

1. Click the Tools menu. 2. Click the Options... menu item. 3. Expand the Debugging node. 4. Click on the Symbols node.

5. Use the Add toolbar button to add a symbol server location, which are Code- view (.pdb) symbol files; usually they can be found in the Debug folder. The following URL links to service packs for Visual Studio 8: http://connect.microsoft.com/VisualStudio/content/content.aspx?ContentID=4324

5.2.2 Setting breakpoints in the code For each variable with an interesting value or start of a function that is problematic, a breakpoint can be inserted via Toggle breakpoint of the Debug menu option or via F9 (see figure 5.3). When a breakpoint is set, the execution of the code will be stopped at that point so that it is possible to inspect the variable values. To continue executing the code from a breakpoint onwards, select ’Continue’ from the Debug menu or press F5.

24 Figure 5.3: The red dot indicates a breakpoint

25 5.3 Run the BrainVoyager QX plugin while debugging

5.3.1 Starting the debugging There are two ways to run the plugin while debugging. The first possibility is to start BrainVoyager QX from Visual Studio via the ’Start Debugging’ option of the Debug menu (see figure 5.4). This only works when “Merge environment” is set to “Yes” (see paragraph 5.2.1).

Figure 5.4: Start debugging

The second way is to start BrainVoyager QX and then via the Debug menu option in Visual Studio attach to the process id of BrainVoyager QX (see figure 5.5).

26 Figure 5.5: The process can be chosen via the Attach to process dialog

27 Viewing values of variables In Visual Studio 8, it is possible to inspect the values of the data via datatips. While scrolling with the mouse over a variable, the datatip will reveal its value (see figure 5.6).

Figure 5.6: While scrolling over a variable, the datatip will reveal its value

Also, when debugging, it is possible to add a watch on a variable. In this case the variable value will be visible in the ’Watch’ window.

28 5.3.2 Solving problems 1. Cannot return from Visual Studio to plugin From the Debug menu, choose ’Con- tinue’ or click ’F5’.

2. Cannot start BrainVoyager QX from Debug menu or error: SXS unable to resolve root system In the Configuration Properties for the project, in the Debugging section, set “Merge Environment” to ”Yes” (is default “No”).

29 5.4 Debugging on Mac OS X

To get an impression of the symbols that are included when debugging, see figure 5.7. For enabling debugging symbols, see figure 5.8.

Figure 5.7: Project symbols in an XCode project

Figure 5.8: Enabling symbols in an XCode project

If BrainVoyager QX is running already, the project can be attached to its process ID (see figure 5.9).

30 Figure 5.9: If BrainVoyager is running already, the project can be attached to its process ID

31 5.4.1 Solving problems 1. Couldn’t create directory (Mac OS X) Change the permissions for the directory via Get Info or Cmd + I.

2. Error: function xxx() was not declared in this scope If the function is declared in the header file (*.h), then the class name might be lacking in the source code file (*.cpp): function xxx() { ... } (should be function class::xxx() { ... }).

32 Chapter 6

Source control

6.1 Introduction

When a project is of large scale or several people are working on the same project, it is useful to introduce code versioning, so that in case of errors, rollback can be applied to revert to the previous version. Also, it is easier for developers to obtain the current status of the project since developers can add comments when checking in and checking out. The system of source control management (SCM) is that code is maintained in a central database so that the same code is accessible for all developers working on the project. Checking out means that a local copy of the centrally kept code is created. After updating the code, it can be checked in the database again. During editing, usually the file is locked so that no one else can change it in the meanwhile; otherwise, the SCM system assembles a new file of different versions.

6.2 Source control on Windows

Microsoft developed a program called Visual Source Safe to keep track of changes in the code.

6.3 Source control on Mac OS X

For Mac OS X, the source control management (SCM) systems code versioning sys- tem (cvs) or its successor subversion (svn) can be used.

6.4 Source control on Linux

Also on Linux, the cvs or its successor subversion can be used.

33 Bibliography

[1] R. Goebel, F. Esposito, and E. Formisano. Analysis of fiac data with brain- voyager qx: From single-subject to cortically aligned group glm analysis and self-organizing group ica. Human Brain Mapping, 27(5):392–401, 2006. [2] W.A. Press, S.A. Teukolsky, W.T. Vettering, and B.P. Flannery. Numerical Recipes in C; The Art of Scientific Computing. Cambridge: Cambridge University Press, 2002.

34 Appendix A

Document history

Document version: 0.4 • Added the IDEs Code::Blocks and Qt Creator.

• Added section on including (scientific) pre-compiled libraries. Document version: 0.3 • Added building information

Document version: 0.2 • Added information about IDEs • Added configuration chapter

35