# ModernGL basics: compile shader

**URL:** <https://discourse.julialang.org/t/moderngl-basics-compile-shader/64393>\
**Category:** General Usage\
**Created:** [July 10, 2021, 2:58am UTC](https://discourse.julialang.org/t/moderngl-basics-compile-shader/64393 "2021-07-10T02:58:12Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![L\_Adam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/l_adam/32/12086_2.png) [@L\_Adam](https://discourse.julialang.org/u/L_Adam)\
**Post date:** [July 10, 2021, 2:58am UTC](https://discourse.julialang.org/t/moderngl-basics-compile-shader/64393/1 "2021-07-10T02:58:12Z")

</div>

I’m getting confused by ModernGL API. It would due to

1. i’m new to using ccall and pointer in julia
2. i’m new to opengl

i try some code found in [this repo](https://github.com/Gnimuc/Videre/tree/master/OpenGL%204%20Tutorials), specifically the simplest part: [triangle](https://github.com/Gnimuc/Videre/blob/master/OpenGL%204%20Tutorials/00_hello_triangle/triangle.jl)

```julia
const vert_source = """
#version 410 core
in vec3 vp;
void main(void)
{
    gl_Position = vec4(vp, 1.0);
}"""
vert_shader = glCreateShader(GL_VERTEX_SHADER)

# from opengl api, the last argument would be pointer to a GLint 
# telling the length of the each source code 
# while GLint == Int32
# why C_NULL works here 
glShaderSource(vert_shader, 1, Ptr{GLchar}[pointer(vert_source)], C_NULL)
glCompileShader(vert_shader)

# some similar C_NULL usage seen in that script 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, C_NULL) 
# what if i want to specify the offset, what should replace C_NULL

```

and the second question is

```julia
# given i've compiled the shader 
# normally you should check GL_COMPILE_STATUS 
status = Int32[-1]
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, pointer(status)) # is this the right call 
# while checking status, status hasn't changed at all 
# and i think what about this 
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, status)
# still silence 

# then i try this 
status = Int32(-1)
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, status) # this does not look right to me
# and checking status, nothing happens

# and this is the definition of glGetShaderiv
@glfunc glGetShaderiv(shader::GLuint, pname::GLenum, params::Ptr{GLint})::Cvoid

# so what should be the right call 

```

I feel that these are stupid questions and simple search would resolve them, e.g reading [doc](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/) and [source](https://github.com/JuliaGL/ModernGL.jl/tree/master/src). But please someone give me the pill and call me stupid afterwards

---

<div class="post-metadata">

**Author:** ![L\_Adam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/l_adam/32/12086_2.png) [@L\_Adam](https://discourse.julialang.org/u/L_Adam)\
**Post date:** [July 10, 2021, 3:04am UTC](https://discourse.julialang.org/t/moderngl-basics-compile-shader/64393/3 "2021-07-10T03:04:28Z")

</div>

i saw this

```julia
# print errors in shader compilation
function shader_info_log(shader::GLuint)
    max_length = GLint(0)
    @c glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length)
    actual_length = GLsizei(0)
    log = Vector{GLchar}(undef, max_length)
    @c glGetShaderInfoLog(shader, max_length, &actual_length, log)
    @info "shader info log for GL index $shader: $(String(log))"
end

```

and now i want to delete the post

---

<div class="post-metadata">

**Author:** ![L\_Adam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/l_adam/32/12086_2.png) [@L\_Adam](https://discourse.julialang.org/u/L_Adam)\
**Post date:** [July 10, 2021, 3:05am UTC](https://discourse.julialang.org/t/moderngl-basics-compile-shader/64393/4 "2021-07-10T03:05:00Z")

</div>

but what is `&max_length` though

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [July 10, 2021, 3:08am UTC](https://discourse.julialang.org/t/moderngl-basics-compile-shader/64393/5 "2021-07-10T03:08:24Z")

</div>

> [@L\_Adam](#):
>
> ```julia
> # from opengl api, the last argument would be pointer to a GLint 
> # telling the length of the each source code 
> # while GLint == Int32
> # why C_NULL works here
> 
> ```

```julia
void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);

```

The last argument is a pointer and `C_NULL` is `Ptr{Nothing} @0x0000000000000000`, so it’s ok to let `ccall` do the auto-conversion.

```julia
status = Int32[-1]
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, pointer(status))

```

This should be:

```julia
status_ref = Ref{GLint](-1)
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, status_ref)
status = status_ref[]

```

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [July 10, 2021, 3:10am UTC](https://discourse.julialang.org/t/moderngl-basics-compile-shader/64393/6 "2021-07-10T03:10:14Z")

</div>

> [@L\_Adam](#):
>
> but what is `&max_length` though

```julia
julia> @macroexpand @c glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length)
quote
    var"##cref#266" = Ref(max_length)
    var"##cref_ret#267" = glGetShaderiv(shader, GL_INFO_LOG_LENGTH, var"##cref#266")
    max_length = var"##cref#266"[]
    var"##cref_ret#267"
end

```

The `@c` macro is a syntax sugar for doing the above `ref`/`deref` stuff.

---

<div class="post-metadata">

**Author:** ![L\_Adam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/l_adam/32/12086_2.png) [@L\_Adam](https://discourse.julialang.org/u/L_Adam)\
**Post date:** [July 10, 2021, 3:17am UTC](https://discourse.julialang.org/t/moderngl-basics-compile-shader/64393/7 "2021-07-10T03:17:07Z")

</div>

i was asking how opengl figure out the length since we give no info

> If _`length`_ is `NULL` , each string is assumed to be null terminated.

> When passed as a ccall argument (either as a Ptr or Ref type), a Ref object will be  
> converted to a native pointer to the data it references. For most T, or when  
> converted to a Ptr{Cvoid}, this is a pointer to the object data. When T is an isbits  
> type, this value may be safely mutated, otherwise mutation is strictly undefined  
> behavior

make sense now. Thank you 😅
