Learn how to build, debug, and extend the C++ SDK on macOS.
To follow this guide, you need the following things:
projectdefinitio.txt
instructions shown in this guide are identical for all platforms. The only difference between building the SDK on Windows, macOS, or Linux is the way the solution files are generated and how to interact with the IDEs such as Visual Studio, Xcode, or Eclipse.To get started with the C++ SDK, you must first generate a solution using the project tool and then build that solution.
tools
folder of the SDK. The file generate_solution_osx.command
is a batch file that runs the project tool with the correct arguments to generate the solution files for macOS.The Cinema 4D SDK is not shipped with project files for Visual Studio, XCode, or Eclipse. Instead, the project files must be generated with the Project Tool. The project tool is a command-line tool that is used to generate the solution files for the Cinema 4D C++ SDK, reading in projectdefinition.txt
files placed in a solution. The project tool is located in the tools
folder of the SDK and can also be run manually.
To run the project tool in a more convenient fashion, double click the file generate_solution_osx.command
. The script can be used both to create a new solution from scratch or to update an existing solution when source files have been added or removed. The script will open shell, displaying the output of the project tool.
Once the generate_solution_osx.command
script has run, a file named solution_osx.command
will be present in the SDK folder. The file contains the command to forcefully open the generated solution in /plugins/project/plugins.xcodeproj
with the app Xcode
found in 'Applications'.
/Applications/Xcode.app
is the path to the Xcode 13 app. If Xcode is installed in a different location, the script must be edited to reflect the correct path. The script will allow you to open the solution in Xcode by double-clicking it; to some degree also for macOS versions beyond Monterey. But the further you update your macOS beyond the supported versions of Xcode 13, the more likely it is that the script will not work anymore as Xcode is then throwing more and more errors when starting (usually related to duplicate or missing GPU libraries).When your macOS version is strongly incompatible with Xcode 13, you must open the solution manually. To do so, navigate to your Xcode 13 package in the Finder, right-click it, and select Show Package Contents. In the package navigate to Contents/MacOS
and double click Xcode
file. Xcode will now start and do a lot of complaining along the way but will eventually succeed in booting. In Xcode, open the solution by selecting File > Open and then selecting the plugins/project/plugins.xcodeproj
file in the SDK folder.
The solution reflects the structure of the SDK and contains all the projects and files that are part of the SDK. The frameworks folder in the solution contains the content of the frameworks folder of the SDK, here you can find the definition of the Cinema 4D API. A framework bundles a section of the Cinema 4D API that is thematically related, the asset.framework
contains for example the API for the underlying data types of the Asset Browser. Frameworks are also used to include aspects of the Cinema 4D API with a project, so that the header files of that framework can be included in a source file of that project.
The modules folder in the solution contains the content of the plugins folder of the SDK. Here you find the code examples of the SDK and can also place your own code and projects. When getting started with the SDK, we recommend focusing on the examples.main project in the modules folder as the other projects are about more advanced topics.
Before you can build the solution, you must ewabled the legacy build system in Xcode. To do so, go to File > Project Settings and select Legacy Build System (deprecated) from the build system dropdown menu, also tick the checkbox for suppressing deprecation warnings. The legacy build system is required to build the Cinema 4D C++ SDK.
Now we must set the build target to AllTargets in the status bar at the top of Xcode. As the build destination you should choose My Mac for now. When you want to ship a plugin you can choose Any Mac to compile universal binaries that can run both on Intel and Apple Silicon hardware. These settings can also be found in the Product > Scheme (to select a target) and Product > Destination (to select a destination) menus.
You can now build the solution by pressing CMD+B
or selecting Build from the Product menu. The SDK now starts building and doing it for the first time can take a while. Switch to the Report Navigator by clicking the icon in the top left of the Xcode window (where the Project Navigator is located) to see the build progress. When the build has finished you can see the message 'Build succeeded' in the Xcode output window. There should not be any failed projects. If there are, the error messages can also be found in the output window. Feel free to ask for help on the Maxon Developer Forum if you encounter any issues.
Once the build has finished, you can find the compiled plugins binaries in the respective project folders in the plugins folder of the SDK. Each project, i.e., subfolder in the plugins folder will be compiled into its own binary. The compiled binaries are the plugins that can be loaded into Cinema 4D. On Windows, the compiled plugins are .xdl64
files, on macOS .xlib
files, and on Linux .xso64
files.
Now that you have built the Cinema 4D C++ SDK, you can test its binaries by debugging them in Xcode. Running Cinema 4D with a debugger attached allows you to set breakpoints in the SDK code, inspect variables, and make use of debugging features of the Cinema 4D API.
To debug binaries built with the Cinema 4D C++ SDK, you must set the debug application in your build target. The debug application is the Cinema 4D executable that will be started when you start debugging. You must also set the command arguments of the debug application to load the Cinema 4D C++ SDK binaries.
To set these values, open the scheme for the build target by opening Product > Scheme > Edit Scheme. In the scheme editor, select the Run section and set the Executable to the Cinema 4D executable that matches the used SDK.
Then switch to the Arguments tab and set the Arguments Passed On Launch to the string shown below which will tell Cinema 4D to load all plugins in the sdk/plugins/
folder. Alternatively, you could also set the plugin path in the preferences of that Cinema 4D installation.
Now you can press CMD+R
or the grey 'Play' button in the toolbar of Xcode to start the debugger. The debugger will boot Cinema 4D which will also load your plugin. Once Cinema 4D has started, you can check its Extensions menu to see if the C++ SDK has been loaded.
Without closing Cinema 4D and without stopping the debugger in Xcode, you now return to Xcode. There you navigate to the file modules/example.main/source/object/roundedtube.cpp
in the Project Navigator and open it by double-clicking it. In the file, you open the search by pressing CMD+F and search for the definition of the method RoundedTubeData::GetVirtualObjects
. Here you set a breakpoint by left-clicking the line number of one of the lines of the method. The breakpoint should lie within the scope, the curly braces, of the method. The line should now be marked by a blue arrow.
Back in Cinema 4D, you can now invoke the Rounded Tube code example from the Commander by pressing SHIFT+C
and typing Rounded Tube
and then hitting Enter
. Cinema 4D will now create an instance of the RoundedTubeData
object which will try to build its geometry cache. The debugger will halt on your breakpoint because you have set it in RoundedTubeData::GetVirtualObjects()
, the method which is responsible for building the geometry of that plugin.
You can now step through the code by pressing F6
to step over the current line or F7
to step into the current line. You can also inspect variables by hovering over them with your mouse or by adding them to the watch window by right-clicking them and selecting Add Expression.
You can now stop the debugger by pressing the stop button in the toolbar in the top left of Xcode. We will now learn how to print (debug) messages in the Cinema 4D API to its various consoles and how to invoke debug stops from code.
To do that, first disable your breakpoint by again clicking on the blue arrow in the the code editor of the modules/example.main/source/object/roundedtube.cpp
file. Then insert the code shown below into the RoundedTubeData::GetVirtualObjects
the file so that the snip marks line up with the existing code.
Now rebuild the solution by pressing CMD+B
or selecting Build from the Product menu. When the build has finished, start the debugger by pressing CMD+R
or the grey 'Play' button in the toolbar of Xcode. In Cinema 4D, create again an instance of the Rounded Tube object. The debugger will now halt on its own on the first manual halt in your code, the DebugStop
, and then on the second manual halt, the CriticalStop
. Press CTRL+CMD+Y
to continue the execution of the program after each halt.
ApplicationOutput
calls in the Cinema 4D console, you must have the Cinema 4D console open. You can open the Cinema 4D console by selecting Extensions > Console from the Cinema 4D menu. To see output in the maxon console, you must run Cinema 4D with the command line argument g_console=true
or g_consoleDebugger=true
. The former will only show the Cinema 4D console when no debugger is attached, the latter will always show the Cinema 4D console.ApplicationOutput is a relatively expensive call and you should avoid it in production code for everything but critical messages which are meant to be seen by the end-user. When you spam the Cinema 4D console with messages, you not only render it unusable for others but also eat up considerable system resources as rendering the console takes time. DiagnosticOutput is a less expensive call than ApplicationOutput
and should be used for messages that are meant for developers and not for end-users.
There are more output functions available in the Cinema 4D API, see the Console Output for more information. The Output functions all support the maxon string output syntax which is described in the Output Syntax page. The general idea is that the \@
character is used to insert variables into the string and you can pass as many variables as you want to these functions as they are all variadic functions.
DebugStop and CriticalStop are used to halt the execution of the program just like a breakpoint would. DebugStop
will only halt the program when it is being debugged in a debug configuration, CriticalStop
will halt the program in all configurations. These functions can be useful to bake breakpoints into your code to halt a debugger when something truly critical happens that you did not expect to happen. For end-users these functions will not do anything, they are only active when the program is being debugged.
But you might also run into these two functions without using them yourself as they are often used in the Cinema 4D frameworks to halt the program when something unexpected happens. When you hit a DebugStop
or worse, a CriticalStop
, in the frameworks while debugging your plugin, it usually means that you either do something truly wrong or have found a bug in Cinema 4D. Most of our debug stops unfortunately are not very informative and do not have an error message attached. But you can look at the framework code to get a sense of what is going wrong. When you hit a wall in such cases, do not hesitate to ask for help on the Maxon Developer Forum.
Now that you have built and debugged the Cinema 4D C++ SDK, it is time to add your first own plugin.
To add a new plugin to the SDK, you must either create a new project in the SDK solution or create a new solution with a new project. You technically could setup shop in one of the existing SDK projects, e.g., the examples.asset
project, but this would mean you would have to ship your plugin with the binary of the examples.asset
project. You therefore need at least one custom project to ship your plugin(s). Within such project you can have multiple plugins, so that you can ship multiple plugins with one binary.
First you must create a new project folder in the plugins
folder of your solution. The name of the new project folder is irrelevant, but it is sensible to name it after your plugin, e.g., myplugin. In this folder, you need to create a project
folder and in that folder a projectdefinition.txt
file. You also need a source
folder in the project
folder and in that folder a main.cpp
file.
Now you must fill the projectdefinition.txt
file of your new project with instructions for the project tool. The content of your projectdefinition.txt
file in root/plugins/myplugin/project
should look like as shown below:
The projectdefinition.txt
in a project folder is used to describe the project to the project tool. The project tool will generate the solution files for the project based on the information in the projectdefinition.txt
file. The projectdefinition.txt
file must contain at least the following information:
Platform=Win64;OSX;Linux
.Type=DLL
.APIS=cinema.framework;cinema_hybrid.framework;core.framework
.ModuleId=net.maxonexample.myplugin
.To learn more about projectdefinition.txt
files, see the Project Tool page.
"net.maxon."
as they are reserved for Maxon Computer. Plugins using such identifiers will not be loaded by Cinema 4D.The APIS
argument determines which frameworks are included in your project and therefore which header files of the Cinema 4D API you can use in your project. As a third party developer, you can include all frameworks - or at least a broad selection as shown in the examples.main
project - with little to no downsides for your project.
But as a beginner you will usually only need the cinema.framework
, cinema_hybrid.framework
, and core.framework
frameworks. The cinema.framework
contains most parts of the classic API of Cinema 4D, the cinema_hybrid.framework
contains parts of the classic API and the maxon API, and the core.framework
contains important foundational aspects of the maxon API. The cinema.framework
is the most important framework for you as a beginner as it contains most of the classic API of Cinema 4D and with it all the plugin interfaces that are interesting for beginners. The maxon API will only play a minor role in your first steps without you missing out on anything. See Plugin Types for an overview of the different plugins types.
Now you must now decide whether you want to add your plugin to the SDK solution or create your own and new solution. The former is the recommended way as it allows you to have all the code examples of the SDK next to your plugin and also has not real disadvantages except for a bit cluttered working environment. The latter is the way to go when you do not really need the SDK code examples all the time and prefer a clean working environment.
In both cases you must edit the projectdefinition.txt
file in the plugins/project
folder of the SDK. This projectdefinition.txt
file at the root of the plugins
folder contains a list of all projects that are part of the solution. You must either add the name of your plugin folder to the Solution
list or you must remove all projects from the projectdefinition.txt
file except for your own (and optionally delete all other project folders in the plugins
folder).
The content of the projectdefinition.txt
file in the plugins/project
folder for extending the SDK solution should look like as shown below:
The solution definition for a new solution would look similar to the one shown above, but with only your plugin in the Solution
list.
Now that you have taken these steps, you can run the generate_solution_osx.command
script again to update the solution and project files. When you still had the solution open in Xcode, Xcode will reload the solution on its own. Otherwise you can double-click the symbolic link solution_osx.command
in the SDK folder to open the updated solution in Xcode.
generate_solution_osx.command
script. When you add files using the tools of Xcode, it will not place them in the source folder. Your project will still compile but your solution will be different from a pure project tool solution.Now it is time to finally fill your main.cpp
file with the code of your plugin. This section is mostly about the boilerplate code you need to get a plugin up and running and uses the minimal code necessary to implement a plugin. The plugin will be a simple command that opens a message dialog with the text "Hello World!" when invoked.
Most plugins also split up their code into multiple files, the main.cpp
file and one or multiple files that implement the actual plugin. The main.cpp
is usually only used to handle plugin messages sent to the module the main.cpp
is the entry point of, while the actual plugin code is implemented in other files. This example condenses all the code into the main.cpp
file for simplicity.
The content of the main.cpp
file in the plugins/myplugin/project/source
folder should look like as shown below:
The important aspects of getting a module and plugin up an running are:
main.cpp
file of a project.main.cpp
file of a project.C4DPL_INIT_SYS
as shown here. Otherwise, the module and its plugins will not work. This function is usually implemented in the main.cpp
file of a project. See Plugin Messages for more information on the plugin message system.RegisterMyPlugin()
function that is called from PluginStart()
in the module. The RegisterMyPlugin()
function is often implemented in one of the plugin files, e.g., myplugin.cpp
and is then 'included' in the main.cpp
file as a forward declaration.The arguments passed to plugin registration functions such as RegisterCommandPlugin
differs from plugin type to plugin type but there are some commonalties:
CommandData
for a command plugin.To run your plugin, you must now rebuild the solution by pressing F7
. Make sure that you have no build errors and then start the debugger by pressing F5
. In Cinema 4D, you can now find the plugin as Extensions > MyPlugin Menu Label
. When you click the item, a message dialog with the text "Hello World!" will open.