2013-02-25 154 views
2

我正在使用C#和P-Invoke訪問Qt框架(http://qt.digia.com/)中的對象。我似乎沒有遇到使用函數返回簡單類型(或無效)的麻煩,但每當我嘗試使用返回對象的函數時,應用程序都會崩潰。在第三方DLL中調用方法

例如,在QtXml4.dll中,有一個方法QXmlInputSource :: data(void),它返回一個QString類型的對象。這裏是我的包裝類:

public class QXmlInputSource 
{ 
    // PInvoke - class QString QXmlInputSource::data(void) 
    [DllImport("QtXml4.dll", CharSet = CharSet.Unicode, EntryPoint = "[email protected]@@[email protected]@XZ", 
     SetLastError = true, CallingConvention = CallingConvention.ThisCall)] 
    static extern IntPtr data(ref IntPtr Ptr); 

    private IntPtr mPtr; 

    public QXmlInputSource(IntPtr Ptr) 
    { 
     mPtr = Ptr; 
    } 

    public override string ToString() 
    { 
     IntPtr mData = data(ref mPtr); 
     return "Epic Fail"; 
    } 

} 

在這裏的是,掛鉤(使用EasyHook)到一個函數調用,提供了一個有效的QXmlInputSource對象的一些代碼:

// just use a P-Invoke implementation to get native API access from C# (this step is not necessary for C++.NET) 
    [DllImport("QtXml4.dll", CharSet = CharSet.Unicode, EntryPoint = "[email protected]@@[email protected]@@Z", 
     SetLastError = true, CallingConvention = CallingConvention.ThisCall)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool XmlParse(IntPtr Reader, IntPtr Source); 

    // Intercept all calls to parse XML 
    public bool XmlParse_Intercepted(IntPtr Reader, IntPtr Source) 
    { 
     QXmlInputSource XmlSource = new QXmlInputSource(Source); 
     String s = XmlSource.ToString(); 

     // call original API... 
     return XmlParse(Reader, Source); 
    } 

的掛鉤代碼似乎很好地工作。當我在包裝類中調用data()函數時,Qt應用程序崩潰。正如我上面所說的,當函數調用返回一個對象而不是簡單類型時,基於Qt的應用程序就會崩潰。

我試過callingconventions,返回類型,封送等各種組合,但沒有偶然發現任何實際工作。

任何幫助非常感謝。

此外,一般感謝您對網站上的所有貢獻者 - 這是一個無價的資源!

+0

您是否嘗試省略入口點並試圖直接訪問庫? – 2013-02-25 08:53:53

+0

不,因爲沒有EntryPoint屬性,我不知道什麼函數名稱用於靜態extern聲明。記住這些是對象的成員函數,而不是靜態函數。裝飾名稱(例如「?parse @ QXml ...」)是識別正確方法所必需的。 – 2013-02-25 09:05:17

+0

那麼,你有沒有考慮過,如果你沒有一個對象(一個實例),你不能調用方法? – 2013-02-25 09:11:50

回答

3

你不可能希望使用P/invoke調用這樣的C++庫。你只是得到了錯誤的工具。

您需要做的是使用C++/CLI混合模式層來完成這項工作。這不僅有實際工作的明顯好處,而且也會更容易。編寫調用本機Qt DLL的C++代碼。然後使用託管類將該代碼展示給您的C#。最後,您可以簡單地從C#代碼中添加對C++/CLI庫的引用,這很好。

+0

總有希望! :P我會盡力說出你的話。我相信我會在一兩天內回到另一個問題...... – 2013-02-25 21:40:26

+0

我實際上無法滿足你的迴應btw。 – 2013-02-25 21:41:06

+0

直到你有更多的代表,你所能做的就是接受答案。無論如何,我會通過提高你的問題來給你一些代表,這是一個很好的問題。我經常忘記提問。 – 2013-02-25 21:45:55