2

I am trying to use a C function from an unmanaged DLL in C#.

The signature of the function is:

const char*  CDECL get_lame_version       ( void );

I import the function this way:

[DllImport("libmp3lame.dll")]
static extern string get_lame_version();

If I call this function, but I break just before the call, then press F5, an AccessViolationException is thrown.

First the execution breaks just before the call:

here the execution breaks just before the call

then I press F5 and there is the exception:

AccessViolationException

If the execution breaks after the call instead, then there is no exception thrown:

enter image description here

So my question is: is there anything wrong with my code? If not, what is going on?

Edit

Here is the definition of get_lame_version:

/*! Get the LAME version string. */
/*!
  \param void
  \return a pointer to a string which describes the version of LAME.
*/
const char *
get_lame_version(void)
{                       /* primary to write screen reports */
    /* Here we can also add informations about compile time configurations */

#if   LAME_ALPHA_VERSION
    static /*@observer@ */ const char *const str =
        STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " "
        "(alpha " STR(LAME_PATCH_VERSION) ", " __DATE__ " " __TIME__ ")";
#elif LAME_BETA_VERSION
    static /*@observer@ */ const char *const str =
        STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " "
        "(beta " STR(LAME_PATCH_VERSION) ", " __DATE__ ")";
#elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0)
    static /*@observer@ */ const char *const str =
        STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION);
#else
    static /*@observer@ */ const char *const str =
        STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION);
#endif

    return str;
}
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    See [this post](http://stackoverflow.com/questions/162897/marshal-char-in-c-sharp) and [this post](http://stackoverflow.com/questions/370079/pinvoke-for-c-function-that-returns-char) for advice on how to specifically deal with your interop returning a string when the function returns a char*. – Chris O Apr 25 '12 at 10:21

2 Answers2

1

The pinvoke signature is wrong. It should be:

[DllImport("libmp3lame.dll", CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr get_lame_version();

And to call it you need to do this;

string version = Marshal.PtrToStringAnsi(get_lame_version());

You can't rely on the p/invoke marshaller to marshal the string value because it does not own the string. The DLL owns the string.

What's more, you should be specifying the calling convention for the LAME DLL functions, otherwise you will end up with the default pinvoke calling convention, stdcall. That does not matter for a function with no parameters but it's a good habit to get into.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    I don't put such comments usually, but thanks a ton for both your answers! –  Apr 25 '12 at 11:55
0

The access violation is caused by the unmanaged code, not your C# code. It's quite hard to say what the problem is without seeing the unmanaged code.

zmbq
  • 38,013
  • 14
  • 101
  • 171