none
Size limit on string returned via PInvoke? RRS feed

  • Question

  • Hi, all -

     

    I asked this question in the general C# forum but struck out. I'm hoping a forum more focused on interop issues may help.

     

    I have an OpenGL display component I've written in C#. It's always worked fine... until I installed a new video board. With this one video board, it throws an AccessViolationException when PInvoking the native method 'glGetString' with a parameter of 'GL_EXTENSIONS'. Now, this same method call succeeds on this machine when used in a native C++ app, it works (in C#) on other machines, it worked (in C#) on this machine with other video boards (some from the same vendor, others not).

     

    The one significant difference I can see is the length of the returned string. The new board supports a larger number of extensions and so returns a significantly longer string - it's ~3000 characters long (I checked with the C++ version of the same code).

     

     

    The DllImport, in a NativeMethods class, looks like this:

    Code Snippet

    [DllImport("opengl32.dll", EntryPoint = "glGetString")]

    public static extern String GLGetString(int flag);

     

     

    And it's called as so:

     

    Code Snippet

    String ext_str = NativeMethods.GLGetString(NativeMethods.GL_EXTENSIONS);

     

     

     

    So my question is: What might cause this to fail on this 1 particular video board? Am I correct in suspecting a marshalling problem caused by the length of the returned string? If so, how does one acquire a string return value from a native API call, if the string is so long?

     

    Thanks for any help offered.

    Monday, May 5, 2008 4:37 PM

Answers

  • This is a tricky function signature.  The P/Invoke marshaler is going to try to free the unmanaged string with CoTaskFreeMem().  That will cause an exception on Vista (not XP).  You'll have to prevent this from happening by doing your own marshaling:

    [DllImport("opengl32.dll", EntryPoint = "glGetString")]
    public static extern IntPtr GLGetString(int flag);
    ...
      IntPtr mem = GLGetString(...)
      String s = Marshal.PtrToStringAnsi(mem);

    Maybe it's Marshal.PtrToStringUni(), not sure.

    Monday, May 5, 2008 11:41 PM
    Moderator

All replies

  • This is a tricky function signature.  The P/Invoke marshaler is going to try to free the unmanaged string with CoTaskFreeMem().  That will cause an exception on Vista (not XP).  You'll have to prevent this from happening by doing your own marshaling:

    [DllImport("opengl32.dll", EntryPoint = "glGetString")]
    public static extern IntPtr GLGetString(int flag);
    ...
      IntPtr mem = GLGetString(...)
      String s = Marshal.PtrToStringAnsi(mem);

    Maybe it's Marshal.PtrToStringUni(), not sure.

    Monday, May 5, 2008 11:41 PM
    Moderator
  • That fixed it, all right. Actually, though, it was blowing up on XP, too. (It's a .NET 2.0 component, if that matters.) It did used to work on XP but not after I installed the new board with the really long extension string.

     

    Thanks for the fix.  

    Tuesday, May 6, 2008 2:44 PM