2013-03-07 92 views
1

EDIT(謝謝ildjarn!): 解決了通過改變委託(和回調函數簽名匹配),以C#回調給訪問衝突

[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(); 
    } 
} 
+0

爲什麼'InstallStatusDel'的第一個參數是StringBuilder而不是'string'? 'StringBuilder'用於_mutable_字符串。在任何情況下,您可能想要將'[MarshalAs(UnmanagedType.LPStr)]'添加到所述參數中。 – ildjarn 2013-03-07 20:12:33

+0

這就是問題所在!謝謝! – 2013-03-07 20:15:23

回答

2

通過改變委託(和回調函數簽名匹配)解決了

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

謝謝你ildjarn!