1


1

DllImportの戻り値でchar []をIntPtrまたはStringBuilderに置き換えると、プログラムが正しいエントリポイントを見つけられなくなるのはなぜですか?

編集:これは関数ではなくマクロとして定義されていることに気付きました。 DLLからC#にマクロをどのようにインポートしますか? (これは新しい質問である必要があります)。

これは私がちょうど尋ねた質問に関連しています:

_ https://stackoverflow.com/questions/1757448/how-do-i-properly-return-a-char-from-an-unmanaged-dll-to-c [アンマネージドDLLからCharを適切に返す方法C#?] _

いくつかの答えは、関数シグネチャをIntPtrまたはStringBuilderに変更することを示唆しています。 グーグルのいくつかのサイト、特にhttp://www.pcreview.co.uk/forums/thread-1378860.php[here]でもこれらのソリューションを見ました。 (他にもありましたが、リンクを探す時間はありません)。

関数シグネチャ:

[DllImport("api.dll")]
internal static extern char[] errMessage(int err);

戻り値の型を変更すると、次の例外がスローされます。

_ 「DLLに「errMessage」という名前のエントリポイントが見つかりません」 _

それがうまくいかなかった場合、人々がこれを提案すると想像することはできません。 私はここで何か悪いことをしていますか? 足りないものはありますか? 残念ながら、私のC / C ++スキルはひどいので、本当に単純なものを見逃している可能性があります。 助けてくれてありがとう。

編集:ドキュメントからの関数署名:

char * errMessage(int err);

4 Answer


2


C / CLIラッパーを作成します。 これは、C#と管理されていない(古い)C / C の間のギャップを埋める驚くほど簡単で強力な方法です。


1


編集:マクロのインポートを反映するように更新されました:

_ できません _

さて、あなたができることは、マクロが何をするかを見て、それをP / Invokeで実装することです。 以下のアドバイスも同様です。

'' '' '

Platform Invoke(P / Invoke)を使用する場合は、できるだけ明示的にすることが最善です。

internal static class NativeMethods
{
    private static string DllName = @"api.dll";

    // This uses 'string' assuming you do not have to free the memory.
    [DllImport(DllName, EntryPoint = "errMessage",
         CharSet = YourCharacterSet,              // CharSet.Ansi? .Unicode?
         CallingConvention = DllCallingConvention // .StdCall? .Cdecl?
    )]
    public static string errMessage(int errorCode);
}

さらに、メソッドをより「.Net」にする管理されたエントリポイントを提供することが最善です。 これは、呼び出し元が割り当てたメモリが適切な時間保持されることを保証する場所です(http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx [ SafeHandle])またはその他の手振りが処理されます。

`errMessage`が文字列を返すと仮定すると、割り当て解除の責任はありません:

public static class ManagedMethods
{
    public static string ErrorMessage(ErrorCode errorCode)
    {
        return NativeMethods.errMessage((int)errorCode);
    }
}


0


ポインターを返すようにC / C ++メソッドを変更する必要がある場合がありますが、関数から文字の配列を返すDllImportを見たことはありません。 関数errMessage内でAPIコードを変更することをお勧めします。おそらくchar []を返す代わりに、api.dllライブラリのcharへのポインタを返すことができます。

void errMessage(int err、char * ptr);

2番目の注意事項…​これを使用して標準のWin APIエラーコードを返しますか?Marshal.Win32Errorクラスがあります。 どう思いますか? Tom.


0


呼び出し規約はstdcallではないようです(これはDllImportが使用するデフォルトの規約です)。 C / C ++は、特に宣言されていない場合、CDECL呼び出し規約を使用します。 したがって、この呼び出し規則をDllImport呼び出しに追加する必要があります。