Android NDK,CRTP和Factory设计模式

时间:2013-01-24 11:40:03

标签: android c++ templates android-ndk crtp

我正在尝试采用Curiously Recursive Pattern Template(CRTP)在我的应用程序中实现一种工厂。

我开始在this nice post之后开发我的CRTP版本。通过CRTP,您只需将它们声明为奇特模板的子类,就可以注册工厂产品的新实现。下面我粘贴了一个我正在使用的代码的简短示例,它与问题中的示例非常类似。

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();
};

如您所见,一旦声明了类sub,就应该使用参数<1, sub>创建一个新的crtp模板。模板类crtp声明了一个静态const uint8_t CRTP_ID,它也在crtp构造函数中引用。静态常量变量用:

实例化
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。在CRTP_ID初始化期间,该类已在工厂中注册

我目前正在使用ndk r8d和sdk 21.0.1。

现在问题。如果我使用默认的gcc编译器编译我的项目一切正常,crtp的子类会自动注册,如果我用android工具链编译我的项目,子类永远不会注册。

我做错了什么?

修改

我的android应用程序完全使用NativeActivity在c ++中实现。我已经定义了一个创建和处理OpenGLEs上下文的状态对象。当Android通知状态窗口已准备好显示时,它会创建GL上下文并加载要渲染的网格。

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);
}

GeometryManager::loadModel加载文件中的几何体和材质。对于网格中找到的每种材质,它使用此函数创建一个新的MaterialData对象:

static MaterialData* create(aiMaterial* material);

在MaterialData :: create函数中,查询Factory以获取正确的着色器来渲染材质。

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

我知道ShaderFactory::dispense(1)不是获取着色器的正确方法,但我正在使用它来验证着色器是否在工厂中创建。

谢谢!

0 个答案:

没有答案