Include 3rd party C code in juce module

Hi,

I want to include 3rd party C code in my JUCE module. The code consists of a set of main .h/.c files and several other .h/.c files included in the main files.

I tried to include main_file.h in my_module.h and main_file.c in my_module.cpp like I usually do with my own files.
But I get a lot of “undefined symbols” errors. It seems that the .c files are not compiled correctly. I tried to include all .h/.c file in my_module.h/.cpp. Compilation seems fine then but now I have a lot of “redefinition errors”. Several source files are using defines like #define BLOCKS_PER_FRAME that are now getting mixed up.

I want to avoid editing the third party code. Is there another way to include everything correctly without the need to edit the #defines ?

Thanks
Stefan

Are there any build instructions along with these C sources?

First of all, this document gives you a good overview of how JUCE modules work. It states that all .cpp files added to your module root are compiled, but does not mention .c files, so it’s possible that directly compiling C files from within the module root is not possible.

Depending on some design choices, some projects might not expect to be built with a unity build schemes were all translation units are included in one big master file and then compiled in one run. So if your my_module.cpp looks somewhat like that

#include "my_module.h"

#include "thirdParty/foo.c"
#include "thirdParty/bar.c"
#include "thirdParty/baz.c"

the preprocessor will just create a big temporary file with the content of all four files merged, which might mess up the later files because they now see definitions from the other files which were usually only visible for that certain file if it was compiled on its own. You could now add multiple .cpp files to your project root which all just include a single .c file from your third party library and see if that resolves the error. Depending on the count of source files in your third party project this could be feasible or not :wink:

Another option to consider is compiling the C library into a static library for all your target platforms and add that precompiled library and only the headers to the module.

Last but not least, if you third party headers contain lines like these

#ifdef __cplusplus
extern "C" {
#endif

simply compiling the C files from within a cpp file could lead to linker errors as the linker searches for functions symbols according to the C conventions while the compiler generated symbols according to the C++ name mangling conventions.

Is the third party project you are trying to wrap open source so that you could share a link to it here?

unfortunately not. Before trying to move the code to a module, I could include the main_file.h to a JUCE test project and compile the code without any issues. It is only screwing up with the unity build scheme in the module.

Yes it looks like this, with additional .h/.cpp files as well

that would get very messy. I haven’t count the files but there are at least 20 files.

that was also my next idea. The source code itself is platform independent. But I assume I will have to compile for all separated targets indecently, right?

Yes, those are everywhere in the code :roll_eyes:

Unfortunately the source code is closed source and per NDA, I’m not allowed to share anything…

I assume that you added all the single .c files to your project via the Projucer/CMake when you tried that? In that case indeed the compiler will compile them all as single translation units and will treat them as C sources, not as C++, which should lead to the expected result.

Wrapping all that into a static library seems like the easiest way to go, at least with the limited set of information you are able to share here.

Excactly. A static library is basically the output of a compiler in a format that can be handed over to the linker, so you need to generate a version for every platform that you are targeting, at best with the same compiler toolchain that you are using to build your project on that platform. Which platforms are you targeting?

By the way, if you are using CMake, this task will be a lot easier, since you could just create a CMake library target and link against that. This way the library would just be built along with your project without the need to perform extra steps manually. If you are using the Projucer, your choices are a lot more limited here unfortunately and you will need to do that compilation manually.

yes exactly. I added all files and #included the main header file in my plugin processor class

okay, I’ll give it a try with static libraries. didn’t jump to CMake until now and it’s getting more and more complicated with issues like that. Maybe it’s now a good moment to do the switch… I’m targeting at least macOS x86 and arm64 as well as Windows. Maybe iOS and Android as well later on.

thanks PluginPenguin! :+1:

Another thing you could try is to #include those .c files that you have, in a module file that has “.c” extension instead of .cpp.
That may produce the expected result (depending on all what was written above)

Are C files actually handled by the JUCE module format? I don’t think so, but I might be wrong here.

From this discussion, it seems they are (were?). I think it’s worth trying.

thanks for the link. I missed that thread… I even did that kind of separation with obj-c code a year ago. makes perfectly sense now with the .c file instead of a .cpp. :see_no_evil:

However, I’m still struggling with the internals of my C-code. If I only #include the main .h/.c files in myModule.h/.c (which them in turn are including the other files), I got undefined symbols from the internal .h/.c files. And if I’m adding all h./.c files in myModule.h/.c files, I got macro redefinitions.

That doesn’t happen when I’m adding those files directly to my project…