我正在尝试使用C#中非托管DLL的C函数。
该功能的签名是:
const char* CDECL get_lame_version ( void );
我以这种方式导入函数:
[DllImport("libmp3lame.dll")]
static extern string get_lame_version();
如果我调用此函数,但在调用之前中断,则按F5,抛出AccessViolationException。
首先执行之前
。
然后我按F5,有例外:
如果执行在调用之后执行,则不会抛出任何异常:
所以我的问题是:我的代码有什么问题吗?如果没有,发生了什么?
修改
以下是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;
}
答案 0 :(得分:1)
pinvoke签名错误。它应该是:
[DllImport("libmp3lame.dll", CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr get_lame_version();
要打电话给你,你需要这样做;
string version = Marshal.PtrToStringAnsi(get_lame_version());
您不能依赖p / invoke marshaller编组字符串值,因为它不拥有字符串。 DLL拥有字符串。
此外,您应该为LAME DLL函数指定调用约定,否则最终将使用默认的pinvoke调用约定stdcall
。这对于没有参数的函数来说无关紧要,但这是一个很好的习惯。
答案 1 :(得分:0)
访问冲突是由非托管代码引起的,而不是您的C#代码引起的。如果没有看到非托管代码,很难说出问题是什么。