Unresolved linker errors in PluginProcessor that don't occur in test class

I have a class called ExampleApp, which inherits a few functions from a class I made to represent App type classes.

I have this code, which runs fine:

#pragma once

#include "ExampleApp.h";

class test {
    ExampleApp exampleApp;
};

But, when I try to do this in PluginProcessor.h, I get linker errors telling me my functions in ExampleApp.h cannot be found.

#pragma once

#include <type_traits>
#include <JuceHeader.h>
#include "test.h"

//==============================================================================
/**
*/
class None2AudioProcessor  : public juce::AudioProcessor
                            #if JucePlugin_Enable_ARA
                             , public juce::AudioProcessorARAExtension
                            #endif
{
public:
    test exampleApp;
...

The same error occurs if I create an ExampleApp directly, vis a vis:

#pragma once

#include <type_traits>
#include <JuceHeader.h>
#include "ExampleApp.h"

//==============================================================================
/**
*/
class None2AudioProcessor  : public juce::AudioProcessor
                            #if JucePlugin_Enable_ARA
                             , public juce::AudioProcessorARAExtension
                            #endif
{
public:
    ExampleApp exampleApp;
...

The errors are mostly LNK2019, with two being LNK2001.

What could be causing this? It seems to be something directly related to JUCE’s PluginProcessor class, so I am curious to know if there’s something I’m missing.

(I probably missed the edits while commenting)

Confused…

1 Like

I was checking to see if making a basic class, including ExampleApp.h, and creating an instance of ExampleApp as a member of the class would work, in general, to see if it’s an issue with my code or if it has something to do specifically with its usage with JUCE’s PluginProcessor.

What I noted is that in the test class, the program built without any errors, but in JUCE’s PluginProcessor class, I get linker errors telling me the functions from ExampleApp do not exist.

Right, I had to make an edit. I had flipped the include test.h and ExampleApp.h in the second and third parts.

1 Like

Do you use the Projucer? If so, are the files you use all included?

Yes, I use Projucer. Which files do you mean?

ExampleApp.cpp for instance.

Nevermind, we can’t see what functions your ExampleApp class has, are they public for instance?
How can we help you find something that we are also not seeing :wink:

What is in ExampleApp.h?

These sources are also a bit confusing because of the writing style. Most coders start classes with an uppercase and instances/variables with a lowercase letter.

This is not related to the PluginProcessor class.

test is a temporary class, ExampleApp is written using Pascal Case, and the variable uses Camel Case.

Here are the linker errors

2>none2.lib(PluginProcessor.obj) : error LNK2019: unresolved external symbol "public: __cdecl none2::processor::AudioData::AudioData(class std::vector<class std::vector<double,class std::allocator<double> >,class std::allocator<class std::vector<double,class std::allocator<double> > > >)" (??0AudioData@processor@none2@@QEAA@V?$vector@V?$vector@NV?$allocator@N@std@@@std@@V?$allocator@V?$vector@NV?$allocator@N@std@@@std@@@2@@std@@@Z) referenced in function "public: virtual class none2::processor::ProcessorResult __cdecl ExampleApp::processor(class none2::processor::AudioData,int,int)" (?processor@ExampleApp@@UEAA?AVProcessorResult@0none2@@VAudioData@03@HH@Z)
2>none2.lib(PluginProcessor.obj) : error LNK2019: unresolved external symbol "public: class std::vector<class std::vector<double,class std::allocator<double> >,class std::allocator<class std::vector<double,class std::allocator<double> > > > __cdecl none2::processor::AudioData::getData(void)const " (?getData@AudioData@processor@none2@@QEBA?AV?$vector@V?$vector@NV?$allocator@N@std@@@std@@V?$allocator@V?$vector@NV?$allocator@N@std@@@std@@@2@@std@@XZ) referenced in function "public: __cdecl none2::modulator::ModulatorResult::operator class std::vector<class std::vector<double,class std::allocator<double> >,class std::allocator<class std::vector<double,class std::allocator<double> > > >(void)const " (??BModulatorResult@modulator@none2@@QEBA?AV?$vector@V?$vector@NV?$allocator@N@std@@@std@@V?$allocator@V?$vector@NV?$allocator@N@std@@@std@@@2@@std@@XZ)
2>none2.lib(PluginProcessor.obj) : error LNK2019: unresolved external symbol "public: class std::shared_ptr<class juce::Slider> __cdecl none2::gui::GUI::Slider::getSlider(void)" (?getSlider@Slider@GUI@gui@none2@@QEAA?AV?$shared_ptr@VSlider@juce@@@std@@XZ) referenced in function "public: virtual class std::shared_ptr<class none2::gui::GUIResult> __cdecl ExampleApp::gui(void)" (?gui@ExampleApp@@UEAA?AV?$shared_ptr@VGUIResult@gui@none2@@@std@@XZ)
2>none2.lib(PluginProcessor.obj) : error LNK2019: unresolved external symbol "public: class none2::processor::AudioData __cdecl none2::modulator::Modulator::runModulator(int,class none2::processor::AudioData &)" (?runModulator@Modulator@modulator@none2@@QEAA?AVAudioData@processor@3@HAEAV453@@Z) referenced in function "public: virtual class none2::modulator::ModulatorResult __cdecl ExampleApp::runModulator(class none2::processor::AudioData,int,int)" (?runModulator@ExampleApp@@UEAA?AVModulatorResult@modulator@none2@@VAudioData@processor@4@HH@Z)
2>none2.lib(PluginProcessor.obj) : error LNK2001: unresolved external symbol "public: virtual class none2::processor::AudioData __cdecl none2::None2App::runProcessor(float * *,float * *,int,int,int)" (?runProcessor@None2App@none2@@UEAA?AVAudioData@processor@2@PEAPEAM0HHH@Z)
2>none2.lib(PluginProcessor.obj) : error LNK2001: unresolved external symbol "public: virtual class std::shared_ptr<class none2::gui::GUIResult> __cdecl none2::None2App::getGUI(void)" (?getGUI@None2App@none2@@UEAA?AV?$shared_ptr@VGUIResult@gui@none2@@@std@@XZ)

Here is ExampleApp.h, a header-only document.


#pragma once


#include <vector>
#include <string>
#include <functional>
#include <cassert>
#include <JuceHeader.h>
#include "Framework/FrameworkHeader.h"

using namespace std;
using namespace juce;

using namespace none2;

class ExampleApp : public None2App
{
	// Audio plugin is made of three major components
	// 1) Processor
	// 2) Modulators
	// 3) GUI

	modulator::Modulator modulator;

	long long int runningSampleNum = 0;

	


public:

	ExampleApp() : None2App() {};

	processor::ProcessorResult processor (
		processor::AudioData input,
		int numChannels = 2,
		int sampleNum = 0) override {

		int sampleNumNow = sampleNum;
		// Produce Sine Wave
		for (auto& samples : input.getData()) {
			for (int channel = 0; channel < numChannels; ++channel) {
				samples[channel] = sin(sampleNumNow);
			}
			++sampleNumNow;
		}

		// Run modulator
		input = static_cast<processor::AudioData>(runModulator(processor::AudioData(input), sampleNum, 1));


		runningSampleNum = sampleNumNow;

		return processor::ProcessorResult(input);
	}

	modulator::ModulatorResult runModulator(processor::AudioData input, int sampleNum, int modIdx) override {
		sampleNum; // To clear unreferenced warning
		// Run modulator on input
		input = modulator.runModulator(modIdx, input);

		return modulator::ModulatorResult(input);
	}

	shared_ptr<gui::GUIResult> gui() override {
		// Make GUI with slider
		shared_ptr<gui::GUI::Slider> slider;

		shared_ptr<gui::GUIResult> result;
		result->addComponent(slider->getSlider());



		return result;
	}





};


Here is the virtual, inherited, class, NoneApp.h,

#pragma once
#include "AudioData.h"
#include "Modulator.h"
#include "GUI.h"
#include "Processor.h"

namespace none2 {
	class None2App {
	public:
		virtual processor::ProcessorResult processor(processor::AudioData input, int numChannels, int sampleNum) = 0;
		virtual modulator::ModulatorResult runModulator(processor::AudioData input, int sampleNum, int modIdx) = 0;
		virtual shared_ptr<gui::GUIResult> gui() = 0;

		None2App() {};

		virtual processor::AudioData runProcessor(
			float** writePointer,
			float** readPointer,
			int bufferSize,
			int numChannels = 2,
			int sampleNum = 0);

		virtual shared_ptr <gui::GUIResult> getGUI();

		operator juce::Component* ();
	};
}

Here is its source file, NoneApp.cpp:

#include "None2App.h"

using namespace none2;

inline processor::AudioData None2App::runProcessor(float** writePointer, float** readPointer, int bufferSize, int numChannels, int sampleNum) {
	writePointer; // To clear unreferenced warning
	return processor(processor::AudioData(readPointer, bufferSize, numChannels), numChannels, sampleNum);
}

inline shared_ptr<gui::GUIResult> None2App::getGUI() {
	return gui();
}

inline None2App::operator juce::Component* () {
	juce::Component* result = gui().get();
	return result;
}

The real thing is, is I have not a clue why it would work in test.h and not work in JUCE’s PluginProcessor class.

Well, this style of writing is certainly “not my favorite”… A lot of choices that can be challenged.

Anyway:

You have not written implementations for the virtual methods you declared with " = 0 ".

The pure virtuals:

virtual processor::ProcessorResult processor(processor::AudioData input, int numChannels, int sampleNum) = 0;
virtual modulator::ModulatorResult runModulator(processor::AudioData input, int sampleNum, int modIdx) = 0;
virtual shared_ptr<gui::GUIResult> gui() = 0;

Are used as:

	processor::ProcessorResult processor (
		processor::AudioData input,
		int numChannels = 2,
		int sampleNum = 0) override {
		...
		
	}

	modulator::ModulatorResult runModulator(processor::AudioData input, int sampleNum, int modIdx) override {
		...
	}

	shared_ptr<gui::GUIResult> gui() override {
		...
	}

I seriously recommend using tools like AppCode and/or ReSharper to have issues like these highlighted and explained while you are editing. Your coding will really improve with tools like them.

This code is too dense and overly complicated for guessing fixes.

And the implementations you now post, where not in your previous code samples…

If the implementations I post now are not in the previous code samples, then there’s something besides C++ going on, as is obvious from here.

Not sure why you don’t like my coding style. It’s perfectly idiomatic and completely clean and simple. Considering what you said about my implementations not showing up, I do wonder what you are seeing.

Very strange! I’ll take this into consideration. Thanks! Not sure how we can debug this considering the events indicated by these observations. I figured something fishy was going on. I didn’t just start C++ or programming yesterday.

Well, I stay with my remark that I find this code very confusing - and I expect that’s related to the issue.

I probably missed something while scanning your samples 4-5 times… sorry and success

PS: ai, code can always be improved… :wink:

It’s perfectly idiomatic and completely clean and simple

1 Like

I cannot see this file included in any .cpp file.
You are aware that headers are not compiled at all, only cpp files?

They’re compiled when they’re included in the source file they’re used in. Inline functions in the class definition should be fine, but I tried out moving all of the definitions to a source file, and I get the same errors, sadly.

Exactly, but it doesn’t seem to be included anywhere according to what you posted (I searched the whole page using Ctrl+F for ExampleApp.h, not there…)

Good luck with your search :slight_smile:

Very interesting. I tried CTRL+F for Example.h and it led me to the original post, where it is in the code twice (once for the test class and once for JUCE’s class). It’s like aliens are taking over or something! :sweat_smile:

In the text yes, but I cannot find an include statement for it in your code snippets…

Well… I’m not sure in that case.

Maybe a screenshot would be useful:

Really, if you use words like “None2”, “Example”, “test” in your code, people like me and Daniel will feel lost in a small, but very dense forest.

A method with a name like processor, receiving a parameter with namespace processor, etc. etc.

Sorry man, this is not “perfectly idiomatic and completely clean and simple”

I suggest you first refactor the code to express what you want in simple C++, without inlining, without pure virtual methods (let them shout at you in the terminal). Plain headers and implementations. I bet the problem will be gone. This is not about Juce classes.