在第三方DLL中调用方法

问题描述:

我正在使用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

你不可能希望使用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