1

I'm trying to adopt the Curiously Recursive Pattern Template(CRTP) to implement a kind of Factory in my application.

I started developing my version of CRTP following this nice post. Through CRTP you're able to register new implementations of your factory product simply by declaring them as subclasses of the curiously template. Below I pasted a brief example of the code I'm using which is really similar to the example in the question.

class abstractProduct {
    ...
};

template <uint8_t TYPE, typename DERIVED>
class crtp : public abstractProduct{
    uint8_t mType;
protected:
    crtp() : mType(CRTP_ID){}
public:
    enum { _CRTP_ID = TYPE };
    static const abstractProduct* get(){
        static DERIVED* sInstance = new DERIVED();
        return sInstance;
    }
    static const uint8_t CRTP_ID;
};

template <uint8_t TYPE, typename DERIVED>
const uint8_t crtp<TYPE, DERIVED>::CRTP_ID = Factory::reg(crtp<TYPE, DERIVED>::_CRTP_ID, &crtp<TYPE, DERIVED>::get);

typedef const abstractProduct* (*f_dispenser)(void);
class Factory {
    static std::map<uint8_t, f_dispenser>* sDict;

public:
    static uint8_t reg(uint8_t shID, f_dispenser dispenser);
    static bool has(uint8_t shID);
    static const abstractProduct* dispense(uint8_t shID);
};

class sub : public crtp<1, sub>{
    friend class crtp<1, sub>;
protected:
    sub();
public:
    virtual ~sub();
};

As you can see, once you declare the class sub, a new crtp template should be created with the parameters <1, sub>. The template class crtp declares a static const uint8_t CRTP_ID which is also referred in the crtp constructor. The static constant variable is instantiated with :

template <uint8_t TYPE, typename DERIVED>
const uint8_t crtp<TYPE, DERIVED>::CRTP_ID = Factory::reg(crtp<TYPE, DERIVED>::_CRTP_ID, &crtp<TYPE, DERIVED>::get);

CRTP_ID should be guaranteed to be initialized before the first main instruction is executed. During the initialization of CRTP_ID the class is registered in the factory

I'm currently using ndk r8d and sdk 21.0.1.

Now the problem. If I compile my project with the default gcc compiler everything works fine and subclasses of crtp are automatically registered, if I compile my project with the android toolchain, subclasses are never registered.

What I'm doing wrong?

EDIT

My android application is implemented completely in c++ using NativeActivity. I've defined a state object which creates and handles an OpenGLEs context. When the state is notified by Android that the window is ready to be shown, it creates the GL context and loads a mesh to be rendered.

state.cpp
case APP_CMD_INIT_WINDOW:
  LOGI("[state]The window is being shown, get it ready.");
  sSurfManager->init(app->window, app->activity->assetManager);

surfacemanager.cpp
int SurfaceManager::init(ANativeWindow* win, AAssetManager* man){
  ....
  this->mModel = GeometryManager::loadModel("cube.ply", man);
}

The GeometryManager::loadModel loads the geometry and materials from the file. For each materials found in the mesh it creates a new MaterialData object using this function:

static MaterialData* create(aiMaterial* material);

Inside the MaterialData::create function the Factory is queried to get a proper shader to render the material.

MaterialData* MaterialData::create(aiMaterial* material){
  ...
  result->setShader(ShaderFactory::dispense(1));
}

I know that ShaderFactory::dispense(1) is not the right way to obtain the shader but I'm using it to verify if the shader is created in the factory.

Thanks!

Community
  • 1
  • 1
hara
  • 3,274
  • 4
  • 37
  • 55
  • Are you sure you want the factory pattern? It's seldom used in C++. Anyway, the problem almost surely has to do with the Java class that owns your NDK plugin. Can you post the code that loads your library, causing static initializers to run? – Potatoswatter Jan 24 '13 at 12:41
  • Hi, I edited my question. I apologize but I can't post all the code because is too tricky. I hope the flow is understandable enough now. Thanks a lot – hara Jan 24 '13 at 13:26

0 Answers0