Вызов методов в сторонних DLL
Я использую C# и P-Invoke для получения доступа к объектам в рамках Qt ( http://qt.digia.com/). Кажется, у меня нет проблем с использованием функций, которые возвращают простые типы (или void), но всякий раз, когда я пытаюсь использовать функцию, которая возвращает объект, приложение вылетает.
Например, в QtXml4.dll есть метод QXmlInputSource::data(void), который возвращает объект типа QString. Вот мой класс оболочки:
public class QXmlInputSource
{
// PInvoke - class QString QXmlInputSource::data(void)
[DllImport("QtXml4.dll", CharSet = CharSet.Unicode, EntryPoint = "?data@QXmlInputSource@@UBE?AVQString@@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 = "?parse@QXmlSimpleReader@@UAE_NPBVQXmlInputSource@@@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);
}
Код перехвата работает нормально. Приложение Qt падает, когда я вызываю функцию data() в своем классе-обертке. Как я уже говорил выше, приложение на основе Qt, похоже, дает сбой всякий раз, когда вызов функции возвращает объект, а не простой тип.
Я пробовал различные комбинации CallingConventions, типов возврата, Marshaling и т. Д., Но не наткнулся на то, что действительно работает.
Любая помощь высоко ценится.
Также большое спасибо всем участникам сайта - это бесценный ресурс!
1 ответ
Вы не можете надеяться вызвать библиотеку C++, подобную этой, используя P/invoke. У вас просто неправильный инструмент для работы.
Вам нужно использовать слой смешанного режима C++/CLI для выполнения этой работы. Мало того, что это будет иметь очевидную выгоду от фактической работы, это будет гораздо проще. Напишите код C++, который вызывает собственные библиотеки Qt. Затем предоставьте этот код вашему C#, используя управляемые классы. Наконец, вы можете просто добавить ссылку на библиотеку C++/CLI из своего кода C#, и это все хорошо.