Rfcs: It's not possible to get the size of the offset from an arbitrary structure to it's field.

Created on 23 Jan 2015  路  6Comments  路  Source: rust-lang/rfcs

Issue by sstewartgallus
_Wednesday Jul 31, 2013 at 04:38 GMT_

_For earlier discussion, see https://github.com/rust-lang/rust/issues/8144_

_This issue was labelled with: in the Rust repository_


I have the following code at http://gitorious.org/p-x/p-x/blobs/master/src/gl.rs#line465 but it is very ugly. I have to create a data structure so I can calculate the offset from the structure to it's field, and pass it to the low level OpenGL code. To understand the issue better the documentation at http://www.khronos.org/opengles/sdk/docs/man/xhtml/glVertexAttribPointer.xml for the glVertexAttribPointer function may be useful.

impl <'self, S: Zero, T: AttributeValue> DisabledAttribute<'self, T> {
    pub fn vertex_pointer<C: Component<S, T>, State>(
        &self,
        _: &BufferTarget<'self, State, S>,    // Not used just needs to be bound
        normalized: bool,
        component: &C
    ) {
        let handle = self.raw_attribute;

        // Compute the stride, and offset
        let s = &Zero::zero();
        let t = component.access(s);
        let offset = borrow::to_uint(t) - borrow::to_uint(s);

        do self.linked_program.raw_program.context.send_and_recv {
            AttributeValue::vertex_attrib_pointer::<T>(
                handle,
                normalized,
                sys::size_of::<S>(),
                offset
            )
        }
    }
}

The definition of Component:

pub trait Component<S, T> {
    fn access<'r>(&self, &'r S) -> &'r T;
}

A sample implementation:

struct Positions;
impl Component<assets::Vertex, [f32, ..3]> for Positions {
    fn access<'r>(&self, s: &'r assets::Vertex) -> &'r [f32, ..3] {
        &s.position
    }
}
T-lang T-libs

Most helpful comment

We don't have to deal with Drop impls in this case, but the uninitialized approach appears to work in practice: https://github.com/rust-lang-nursery/unix-socket/blob/master/src/lib.rs#L21. It compiles down to a constant.

All 6 comments

The workaround:

macro_rules! offset_of {
    ($ty:ty, $field:ident) => {
        unsafe { &(*(0 as *const $ty)).$field as *const _ as usize }
    }
}

source: https://stackoverflow.com/questions/40310483/how-to-get-pointer-offset-in-bytes/40310851

@gtors That might be UB. I don't know where the previous discussion was.

For the record @gtors's solution caused segfaults in glium.

I believe using an union / mem::uninitialized + mem::drop could work, but you have to be careful about panicking while you have an uninitialized variable on the stack.

We don't have to deal with Drop impls in this case, but the uninitialized approach appears to work in practice: https://github.com/rust-lang-nursery/unix-socket/blob/master/src/lib.rs#L21. It compiles down to a constant.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rust-highfive picture rust-highfive  路  4Comments

torkleyy picture torkleyy  路  3Comments

yongqli picture yongqli  路  3Comments

clarfonthey picture clarfonthey  路  3Comments

3442853561 picture 3442853561  路  3Comments