Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как правильно импортировать строку в C#, из сторонней библиотеки на нативном Си++ 
:(
    Опции темы
Competitor
Дата 8.9.2007, 14:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 440
Регистрация: 23.3.2005
Где: Tula

Репутация: -1
Всего: -1



Привет всем.
Сделал dll'ку на С++, которая работает с WMI и выдает на выход какую-то строку типа BSTR. Я импортирую эту дллку с свой основной проект на C#. Как мне передать значение из С++ дллки в C#, чтобы там оно нормально прочиталось.
Допустим метод в С++ на экспорт выглядит так:
Выделить всёкод C++
Код

private:
    BSTR bstrData;
extern "C" __declspec(dllexport) BSTR GetData()
{
    return bstrData
}

А в C# метод импорта выглядит так:
Выделить всёкод C#
Код

        [DllImport("Test1.dll")]
        public static extern string GetData();

При таком написании вываливается ошибка записи в память. Подскажите плиз как решить эту проблему? 
PM MAIL WWW   Вверх
Stepan_Lameroff
Дата 8.9.2007, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 164
Регистрация: 16.12.2006

Репутация: 9
Всего: 14



А так не пробовали?

Код

[DllImport("Test1.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GetData();

PM MAIL   Вверх
snav
Дата 9.9.2007, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 8.9.2007

Репутация: 2
Всего: 4



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/defa...ymanagement.asp


Это сообщение отредактировал(а) snav - 9.9.2007, 09:28
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0918 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.