0

This function in the Oculus SDK gives error code 0xc0000005:

[DllImport(LibFile)]
private static extern void ovrHmd_GetRenderScaleAndOffset(ovrFovPort fov,
                                                          ovrSizei textureSize,
                                                          ovrRecti renderViewport,
                                                          [MarshalAs(UnmanagedType.LPArray, SizeConst = 2)]
                                                          [Out] out ovrVector2f[] uvScaleOffsetOut);

No other PInvoke functions throw errors, but I think this one's different because the output is an array. Actually there's one other function that returns an array, and it gives the same error:

[DllImport(LibFile)]
private static extern void ovrHmd_GetEyeTimewarpMatrices(IntPtr hmd, ovrEyeType eye, ovrPosef renderPose,
                                                         [MarshalAs(UnmanagedType.LPArray, SizeConst = 2)]
                                                         [Out] out ovrMatrix4f_Raw[] twnOut);

Here are the struct declarations:

[StructLayout(LayoutKind.Sequential)]
public struct ovrVector2f
{
    public float x, y;
}

[StructLayout(LayoutKind.Sequential)]
public struct ovrMatrix4f_Raw
{
    public float m00;
    public float m01;
    public float m02;
    public float m03;

    public float m10;
    public float m11;
    public float m12;
    public float m13;

    public float m20;
    public float m21;
    public float m22;
    public float m23;

    public float m30;
    public float m31;
    public float m32;
    public float m33;
}

Looking at the SDK source, I know at least ovrHmd_GetRenderScaleAndOffset looks pretty boring, I can't imagine the error would come from inside the SDK.

I feel like I need to specify sizes somewhere in the function signature? And I'm wondering if it's limited to output parameters, or any and all "array of struct" parameters.

etodd
  • 483
  • 1
  • 3
  • 8
  • 4.5.2 has has Simd support and vector classes to support. – Jay Sep 05 '14 at 00:07
  • Yea, this very rarely comes to a good end. You are telling the pinvoke marshaller to copy the native array and destroy it. The latter invariably bombs. Only hope you have is getting the declaration wrong, use plain `ovrVector2f[] uvScaleOffsetOut`, no out attributes. And pass an array that's sufficiently large. – Hans Passant Sep 05 '14 at 00:29

1 Answers1

2

The array parameters are declared incorrectly. The use of out introduces a spurious extra level of indirection. You need to pass an array, that you allocate, and let the unmanaged code populate it. Declare the parameter like this

private static extern void ovrHmd_GetRenderScaleAndOffset(
    ovrFovPort fov,                                       
    ovrSizei textureSize,
    ovrRecti renderViewport,
    [Out] ovrVector2f[] uvScaleOffsetOut
);

Allocate the array before calling the function:

ovrVector2f[] uvScaleOffsetOut = new ovrVector2f[2];

FWIW it would have helped had you shown the unmanaged side of the interface.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490