jonp's picture

CHeaderToXML+Bind: String vs. StringBuilder

This was an issue recently reported against the MonoTouch OpenTK binding of the iPhone OpenGLES implementation.

The problem, in short, is this function:

  GL_API void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);

The problem is that CHeaderToXML converts this into:

  <function name="GetProgramInfoLog" extension="Core" profile="" category="2.0" version="2.0">
    <returns type="void" />
    <param type="GLuint" name="program" flow="in" />
    <param type="GLsizei" name="bufsize" flow="in" />
    <param type="GLsizei*" name="length" flow="in" />
    <param type="GLchar*" name="infolog" flow="in" />

Which Bind then turns into:

[System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glGetProgramInfoLog", ExactSpelling = true)]
internal extern static unsafe void GetProgramInfoLog(UInt32 program, Int32 bufsize, Int32* length, String infolog);

The GLchar* is turned into a string. This is wrong, as it needs to be an output buffer, i.e. a StringBuilder.

It looks like Bind does the right thing here, as Structures/Parameter.cs:Translate() looks at the flow direction to decide between StringBuilder and String.

So the problem appears to be CHeaderToXML, as it has code which does:

  Flow = param_name.EndsWith("ret") ? "out" : "in"

In this case, the parameter is "info_log," which obviously doesn't end in "ret". CHeaderToXML needs to be more intelligent, and only specify a flow direction of in if the parameter is const (though I don't know what other effects this may have).



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Ah, this is a simple oversight - this function should have been added to overrides.xml:

  <function name="GetProgramInfoLog" extension="Core">
    <param name="infolog"><flow>out</flow></param>

(GetString, GetShaderSource are already there).

The CL headers actually obey the "ret" convention, so EndsWith("ret") is valid there.

Unfortunately, the 'check for const' solution would not work, even though the headers are const-correct. The issue is that treating all parameters as 'out' by default would break 'in/out' parameters. For example, GL.GenBuffers:

// C signature
void glGenBuffers (GLsizei n, GLuint* buffers);
// C# wrappers
unsafe void GenBuffers(Int32 n, Int32* buffers);
void GenBuffers(Int32 n, Int32[] buffers);
void GenBuffers(Int32 n, ref Int32 buffers);

The last overload would become 'out Int32 buffers', which is wrong - this is an 'in/out' parameter (the user is responsible for allocating the array which will then be filled by ES).

This is one of those corner cases that there's not enough information in the C headers to translate convert them automatically - hence, overrides.xml.

Edit: should document this in CHeaderToXML.

the Fiddler's picture

Update: this is fixed in rev. 2338.