| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Общие вопросы по .NET и C# > Как правильно импортировать строку в C# |
| Автор: Competitor 8.9.2007, 14:49 | ||||
| Привет всем. Сделал dll'ку на С++, которая работает с WMI и выдает на выход какую-то строку типа BSTR. Я импортирую эту дллку с свой основной проект на C#. Как мне передать значение из С++ дллки в C#, чтобы там оно нормально прочиталось. Допустим метод в С++ на экспорт выглядит так: Выделить всёкод C++
А в C# метод импорта выглядит так: Выделить всёкод C#
При таком написании вываливается ошибка записи в память. Подскажите плиз как решить эту проблему? |
| Автор: Stepan_Lameroff 8.9.2007, 15:47 | ||
А так не пробовали?
|
| Автор: snav 9.9.2007, 09:21 |
| Competitor, Скорее всего, ошибка в неправильном декларировании возвращаемого значение на C#. Это связано с особенностями управления памятью при маршалинге. Дело в том, что существует несколько стратегий работы памятью при возврате указателя на строку. Различие состоит в том, кто отвечает за освобождение выделенной памяти и как должно осуществляться освобождение памяти. В твоем примере импортируемая функция объявлена следующим образом: [DllImport("Test1.dll")] public static extern string GetData(); При таком объявлении маршалер .NET использует стратегию, принятую в COM. Т.е. считается, что импортируемая функция DLL выделяет память, а приложение .NET должно ее освободить. Поэтому маршалер, получив указатель на строку BSTR, копирует строку в string, а затем пытается освободить память указателя, вызвав функцию CoTaskMemFree(). Видимо, из-за этого и происходит ошибка. Скорее всего, в твоей DLL применяется подход, подразумевающий, что приложение .NET не должно освобождать память, захваченную для указателя. В этом случае объявление функции должно быть следующим: [DllImport("Test1.dll")] private static extern IntPtr GetData(); Полученный таким образом указатель нужно вручную преобразовать в string, например: public static string GetDataEx() { IntPtr ptr = GetData(); if ( ptr == IntPtr.Zero ) return string.Empty; return Marshal.PtrToStringBSTR(ptr); } Возможно, что вместо метода Marshal.PtrToStringBSTR() тебе нужен другой метод типа Marshal.PtrToStringXXXX() в зависимости от того, какой указатель ты возвращаешь. Более подробно можно почитать в MSDN: http://msdn.microsoft.com/library/rus/default.asp?url=/library/rus/cpguide/html/cpconmemorymanagement.asp |