2012-04-25 21 views
2

C#でアンマネージDLLのC関数を使用しようとしています。DllImportを呼び出す直前にブレークするときにAccessViolationExceptionが発生するのはなぜですか?

関数のシグネチャは次のとおりです。

const char* CDECL get_lame_version  (void); 

私は機能をこのようにインポートします。

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

私はこの関数を呼び出すが、私はちょうど呼び出しの前に壊れた場合は、F5キーを押し、 AccessViolationExceptionがスローされます。

まず実行ブレークはちょうど前にコール:

here the execution breaks just before the call

その後、私はF5キーを押して、例外がある:

AccessViolationException

実行が後を破った場合代わりに呼び出しがあった場合、例外はスローされません。

enter image description here

私のコードに問題はありますか?そうでない場合、何が起こっているのですか?

/*! 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 /*@[email protected] */ const char *const str = 
     STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " " 
     "(alpha " STR(LAME_PATCH_VERSION) ", " __DATE__ " " __TIME__ ")"; 
#elif LAME_BETA_VERSION 
    static /*@[email protected] */ 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 /*@[email protected] */ const char *const str = 
     STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION); 
#else 
    static /*@[email protected] */ const char *const str = 
     STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION); 
#endif 

    return str; 
} 
+1

[this post](http://stackoverflow.com/questions/162897/marshal-char-in-c-sharp)と[this post](http://stackoverflow.com/questions/370079/pinvoke)を参照してください。 -for-c-function-that-returns-char)関数がchar *を返すときに文字列を返すinteropを具体的に扱う方法に関するアドバイスを提供します。 –

答えて

1

pinvoke署名が間違っています。それは次のようにする必要があります。

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

これを行う必要があります。

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

は、あなたはそれが文字列を所有していないので、文字列値をマーシャリングするマーシャラーを呼び出し/ Pに依存することはできません。 DLLが文字列を所有しています。

さらに、LAME DLL関数の呼び出し規約を指定する必要があります。そうしないと、デフォルトのピンボーク呼び出し規約stdcallになります。それはパラメータを持たない関数には関係ありませんが、入るのは良い習慣です。

+1

私はこのようなコメントはしませんが、両方の答えにお返事ありがとうございます! –

0

アクセス違反が、アンマネージコードによって引き起こされていない、あなたのC#コード:

編集ここ

はget_lame_versionの定義です。管理されていないコードを見ずに問題が何であるかを言うのはかなり難しいです。

+0

私は関数の定義を追加しました。 –

関連する問題