来自c++的c#回调会导致访问冲突

C# callback from C++ gives access violation

本文关键字:访问冲突 回调 c++ 来自      更新时间:2023-10-16

编辑(谢谢ildjarn!)通过将委托(和回调函数签名匹配)更改为

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

原始文章:

我有一个用c#编写的。net应用程序调用C dll中的函数的问题。我看过其他线程与类似的问题,但我一定是错过了不同的东西。当我在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();
    }
}

通过将委托(和回调函数签名匹配)更改为

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

谢谢你!