For a personal project, a raspberry pi-controlled guitar pedal, i'm creating a small library. This library contains a bunch of classes specifying the the function of several types of effects. For this I have an Effect base-class that every effect inherits from, together with an EffectFactory base-class that will create sequences of effects based on a configuration file. I'm using c++, a language I'm quite new to as I generally use JavaScript.
EffectFactory consists out of a map of strings mapped with pointers to other EffectFactory instances and two functions; one responsible for registering EffectFactory instances to the factories map, and the other a create function that can be overridden by instances of EffectFactory. My issue arises when I compile the library for testing. I get an error:
undefined reference to `EffectFactory::factories[abi:cxx11]'
There seems to be an issue with using the c++11 ABI. I ran the compiler again with -Wabi-tag added and got:
effect-master/effect.h:22:7: warning: 'EffectFactory' does not have the "cxx11" ABI tag that 'std::string' {aka 'std::__cxx11::basic_string<char>'} (used in the type of 'virtual Effect* EffectFactory::create(std::string)') has [-Wabi-tag]
22 | class EffectFactory
| ^~~~~~~~~~~~~
effect-master/effect.h:26:19: note: 'virtual Effect* EffectFactory::create(std::string)' declared here
26 | virtual Effect *create(std::string config);
| ^~~~~~
In file included from f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\string:55,
from f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\bits\locale_classes.h:40,
from f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\bits\ios_base.h:41,
from f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\ios:42,
from f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\ostream:38,
from f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\iostream:39,
from effect-master/effect.h:4,
from effect-master/effect.cpp:1:
f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\bits\basic_string.h:77:11: note: 'std::string' {aka 'std::__cxx11::basic_string<char>'} declared here
77 | class basic_string
| ^~~~~~~~~~~~
In file included from effect-master/effect.cpp:1:
effect-master/effect.h:29:49: warning: 'EffectFactory::factories' inherits the "cxx11" ABI tag that 'std::map<std::__cxx11::basic_string<char>, EffectFactory*>' (used in its type) has [-Wabi-tag]
29 | static std::map<std::string, EffectFactory *> factories;
| ^~~~~~~~~
In file included from f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\map:61,
from effect-master/effect.h:6,
from effect-master/effect.cpp:1:
f:\programs\mingw\lib\gcc\mingw32\9.2.0\include\c++\bits\stl_map.h:100:11: note: 'std::map<std::__cxx11::basic_string<char>, EffectFactory*>' declared here
100 | class map
| ^~~
From what I can gather there seems to be some sort an incompatibility between EffectFactory and both the std::string and the std::map. I spent some time googling and found the solution of using -D_GLIBCXX_USE_CXX11_ABI=0, but this didn't fix it. I also found this question, but I couldn't make much sense of it and don't know if it applies to my situation. Anyone who can help me understand and maybe fix this issue?
For refrence I am using the MinGW g++ compiler.
effect.h
#ifndef EFFECT_H
#define EFFECT_H
#include <iostream>
#include <string>
#include <map>
#include <regex>
class EffectFactory;
class Effect
{
public:
bool enabled = true;
void toggleEnabled();
virtual void triggerAction();
virtual int eval(int input_signal);
protected:
int output_signal;
};
class EffectFactory
{
public:
static void registerType(const std::string &name, EffectFactory *factory);
virtual Effect *create(std::string config);
private:
static std::map<std::string, EffectFactory *> factories;
};
#endif
effect.cpp
#include "effect.h"
void Effect::toggleEnabled()
{
enabled = !enabled;
};
void Effect::triggerAction()
{
std::cout << "The base triggerAction was triggered\n";
};
int Effect::eval(int input_signal)
{
std::cout << "The base eval was triggered\n";
return input_signal;
};
Effect *EffectFactory::create(std::string config)
{
std::smatch name_match;
std::regex name_regex("^\\S+(?:\\n?)");
std::regex replace_regex("^\\S+\\n?|^ {2}");
std::regex_search(config, name_match, name_regex);
config = std::regex_replace(config, replace_regex, "");
return factories[name_match.str()]->create(config);
};
void EffectFactory::registerType(const std::string &name, EffectFactory *factory)
{
factories[name] = factory;
};
Aucun commentaire:
Enregistrer un commentaire