1

EDIT(ありがとうildjarn!):デリゲート(および一致するコールバック関数の署名)を変更することで解決しました

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void InstallStatusDel([MarshalAs(UnmanagedType.LPStr)]string Mesg, int Status);

元の投稿:

C dll で関数を呼び出す C# で記述された .net アプリケーションに問題があります。同様の質問で他のスレッドを見てきましたが、何か違うものを見逃しているに違いありません。これを C# でデバッグすると、InstallStatusCallback でブレークポイントをヒットできますが、実行が InstallStatusCallback を終了すると、AccessViolationException が発生します。C でデバッグを試みましたが、実行がコールバックから戻る前にアクセス違反が発生します。ご意見ありがとうございます。

C dll のプロジェクト設定は、デフォルトで __cdecl を使用するように設定されています。C DLL ランドでは、次のコードが配置されています。

typedef void (__cdecl *StatusCallback)(const char* Mesg, int Status);
__declspec(dllexport) int Install(void* thing1, void* thing2, void* thing3, StatusCallback Func);


int Install(void* thing1, void* thing2, void* thing3, StatusCallback Func)
{
    Func("msg", 3);
    return 0;
}

C#で私は持っています:

public partial class InstallerStatus : Form
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void InstallStatusDel(StringBuilder Mesg, int Status);

    public static extern int Install(IntPtr thing1, IntPtr thing2, IntPtr thing3, InstallStatusDel Func);
    [DllImport("myDll.dll", CallingConvention = CallingConvention.Cdecl)]

    private IntPtr mThing1;
    private IntPtr mThing2;
    private InstallStatusDel mInstallStatusFunc;
    private BackgroundWorker mInstallWorker;

    public InstallerStatus(IntPtr pThing1, IntPtr pThing2)
    {
        InitializeComponent();

        mThing1 = pThing1;
        mThing2 = pThing2;
        mInstallStatusFunc = InstallStatusCallback;

        mProgressBar.Minimum = 0;
        mProgressBar.Maximum = 100;
        mProgressBar.Value = 0;

        mInstallWorker = new BackgroundWorker();
        mInstallWorker.DoWork += new DoWorkEventHandler(InstallWork);
        mInstallWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(InstallWork_Completed);
    }

    private void InstallWork(object sender, DoWorkEventArgs e)
    {
        Install(mThing1, mThing2, IntPtr.Zero, mInstallStatusFunc);
    }

    private void InstallWork_Completed(object sender, RunWorkerCompletedEventArgs e)
    {
        Close();
    }

    private void InstallStatusCallback(StringBuilder PartName, int Status)
    {
    }

    private void InstallLoad_Shown(object sender, EventArgs e)
    {
        mInstallWorker.RunWorkerAsync();
    }
}
4

1 に答える 1

2

デリゲート(および一致するコールバック関数の署名)を次のように変更することで解決しました

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void InstallStatusDel([MarshalAs(UnmanagedType.LPStr)]string Mesg, int Status);

ildjarnさん、ありがとうございます!

于 2013-03-07T20:18:10.190 に答える