2016-11-05 14 views
1

私はネイティブDLLライブラリをDelphiで書いています。私はこのlibをC#から参照し、返された文字列を取得したいと思います。ネイティブDLL - C#

機能

function GetCode (aUser,aPassword: PAnsiChar): PAnsiChar; stdcall; 

C#コード

[DllImport("C:\\library.dll", CallingConvention = CallingConvention.StdCall, 
     CharSet = CharSet.Ansi)] 
private static extern String GetCode([MarshalAs(UnmanagedType.LPStr)]string aUser, [MarshalAs(UnmanagedType.LPStr)]string aPassword); 

public String getCode(String login, String password) { 
     return GetCode(login, password); 
} 

コード-1073740940(0xc0000374)とコール機能アプリケーション終了を試します。

期限がありますか?助けてくれてありがとう

+0

1.デバッガでこれを呼び出すときに、適切な例外メッセージが表示されますか? 2.関数がエクスポートされていますか? 3.関数名が変更されていますか? 4.あなたはどのように戻り値を解放することになっていますか? –

+0

1.いいえ、アプリケーションはNTSTATUSエラーコードで終了します。 2.そうです。それ以外の場合は、管理例外が発生しています。 3. 2を参照してください。4.非常に良い質問! –

+0

あなたは正しいです@DavidHeffernan、私はまず0xc0000374のためにグーグルをしていたはずです。 (私はOPがデバッガの下で実行されないことによってOPが管理された例外を逃していないことを確かめたかったです) –

答えて

4

戻り値はで、返された文字列を解放する責任はmarshallerが負います。それはCoTaskMemFreeへの呼び出しでそうします。間違いなくあなたの文字列はCOMヒープに割り当てられていません。したがって、STATUS_HEAP_CORRUPTIONのエラーコードNTSTATUSのエラーです。 Marshal.PtrToStringAnsiに戻り値を渡し、文字列を取得するには

[DllImport("C:\\library.dll", CallingConvention = CallingConvention.StdCall, 
    CharSet = CharSet.Ansi)] 
private static extern IntPtr GetCode(string aUser, string aPassword); 

あなたのP /呼び出しは、これを避けるために、代わりにIntPtrを返す必要があります。

また、余分なMarshalAs属性を削除しています。 CharSet.Ansiは入力引数マーシャリングを処理します。

返されたメモリの割り当てを解除する方法については、まだ解決する必要があります。それがどのように割り当てられたのかわかりません。 Delphiコードの開発者に連絡するか、ソースを読む必要があります。ネイティブのDelphiヒープが使用されている場合は驚かないでください。バインドされてしまいます。 CoTaskMemAllocを呼び出すことによってCOMヒープを使用することは実際には悪い選択ではなく、元のp/invoke戻り値stringは問題ありません。

その他のオプションには、デアロケータのエクスポートや、呼び出し元にバッファの割り当てを依頼するオプションがあります。さまざまなオプションを実装する方法については、Web上に非常に多くの例があります。

+0

Delphiでは 'WideString'を、C#では' UnmanagedType.BStr'を使って割り振りと解放を処理できます。ただし、これを戻り値としてではなくパラメータとして使用してください(http:// stackoverflowを参照)。com/questions/9349530/widestring-of-a-function-as-a-function-return-value-for-interop) – Remko

+0

ありがとう:-)これは素晴らしいですが、問題があります返されたメモリの割り当てを解除します。私はMarshal.FreeHGlobal(retval)を使用しました。それでも(終了後に)アプリケーションがクラッシュし、プロセスが死ぬことはありません。あなたは何か考えていますか? –

+0

割り当て方法を工夫しなければならない –

関連する問題