我试图让每个GraphicsContext
实现返回不同的Shader
.
pub trait Resources {
type Shader: shader::Shader;
}
pub trait GraphicsContext {
type Resources: Resources;
/// Creates a shader object
fn create_shader<'a>(&'a self, shader::Stage, source: &str)
-> Result<<<Self as GraphicsContext>::Resources as Resources>::Shader,
shader::CreateError>;
/// Creates a shader program object
fn create_shader_program<'a>(&'a self, shaders: Vec<&shader::Shader>)
-> Result<Box<shader::ShaderProgram + 'a>, shader::ProgramCreateError>;
// more to come
}
这是为了让create_shader_program
方法(和其他方法)知道具体类型,Shader
以便他们可以调用着色器对象上的实现特定方法。
我不想将这些方法(例如setCurrent
or attach
)放入所有实现都必须使用的特征中。并非所有图形 API 都使用相同的系统:OpenGL 是绑定/取消绑定,Vulkan 是结构/设置字段,DirectX 是其他东西等等。
首先,我问这是构建我的引擎的正确方法。我相信在需要这些Shader
对象的框架/应用程序级代码中,我可以根据Context
.
// almost certain this doesn't compile, but should be possible in theory
// I'm trying to say:
// the type of the `shader` argument must match to the associated type
// contained within the `context`
fn do_something_with_shader(context: &GraphicsContext,
shader: ??**GraphicsContext::Resources::Shader**??)
-> Result<Foo, Bar>;
也许:
fn do_something_with_shader<T>(context: &GraphicsContext<T>,
shader: ??**T::Shader**??)
where T: GraphicsContext::Resources -> Result<Foo, Bar>;
这样的事情可能吗?希望你能看到我有点理解基本的泛型(我来自 Java),但这让我发疯了(感觉很hackish)。
如果这是正确的方法,那么我的实施就会出现问题。rustc
希望关联类型具有指定的生命周期。
wrong number of lifetime parameters: expected 1, found 0 [E0107]
opal_driver_gl/src/context.rs:23 type Shader = Shader;
我的OpenGLShader
结构实际上是 type OpenGLShader<'a>
,所以这个错误是有道理的。我的问题是我从这一堆代码中从哪里获得生命周期:
struct OpenGLResources;
impl Resources for OpenGLResources {
type Shader = OpenGLShader;
}
impl GraphicsContext for OpenGLGraphicsContext {
type Resources = Resources;
/// Creates a shader object
fn create_shader<'a>(&'a self, stage: core_shader::Stage, source: &str)
-> Result<<<Self as GraphicsContext>::Resources as Resources>::Shader,
core_shader::CreateError> {
// impl goes here
}
}
我尝试将生命周期附加到OpenGLResources
and OpenGLGraphicsContext
,这解决了错误,但随后说error: parameter 'a is never used
。
所以其次,我问我如何才能在我的关联类型中包含那个生命周期。
非常感谢,如果你能看看这个。我觉得这样的事情必须可以在编译时检查,但我对 Rust 还很陌生,所以我不太了解如何实现它。