Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Получение строк из unmanaged code

10K
02 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Есть функция, написанная на плюсах, которая должна вернуть строку в C#-код. С передачей в DLL все нормально. Параметр типа string передается на параметр типа wchar_t*.

Но когда кода у меня в С++ описана функция как
 
Код:
extern "C" __declspec(dllexport) wchar_t* __stdcall GetString(void* objectHandle);

а в С# ее ищет функция
[CODE=C#][DllImport("MyLyb.dll")]
private static extern string GetString(IntPtr objectHandle)[/CODE]
то в дебаге я получаю исключение
Цитата:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt



Пробовал добавить атрибут

 
Код:
[return: MarshalAs(UnmanagedCode.LPWStr)]
Тоже самое.

Пробовал строку запихать в параметры и пометить как выходной параметр:
 
Код:
extern "C" __declspec(dllexport) void __stdcall GetString(void* objectHandle,  wchar_t* returnString);

[DllImport("MyLyb.dll")]
private static extern voud GetString(IntPtr objectHandle, out string resultString);


Получаю пустую строку, на этот раз без исключения.

Так как правильно получить строку из unmanaged code?
277
02 февраля 2012 года
arrjj
1.7K / / 26.01.2011
Так для Out должно работать
[DllImport("MyLyb.dll")]
private static extern voud GetString(IntPtr objectHandle,[Out,MarshalAs(UnmanagedType.LPWStr)] StringBuilder resultString);
Вместо out попрробуй использовать ref.
Также CharSet попробуй указать для DLL, а то мб за пределы строки вылазит.
10K
02 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Крякозябры... Но уже хоть что-то.

Пробовал все CharSet'ы.
А как StringBuilder правильно инициализировать?
 
Код:
StringBuilder strBuilder = new StirngBuilder();
или
 
Код:
StringBuilder strBuilder = new StirngBuilder(returnStringLength);
?

UPD: С ref возвращается пустая строка.
277
02 февраля 2012 года
arrjj
1.7K / / 26.01.2011
Цитата: Cybernetic
Крякозябры...


О! уже лучше :) Посмотри на wiki какие именно :D

Также попробуй другой UnmanagedType

10K
02 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Цитата: arrjj
Посмотри на wiki какие именно


Забавная таблица :)
Своих крякозябр я не нашел. У меня похоже на японский.
Другие типы сейчас поперебираю.

10K
02 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Цитата: arrjj
Также попробуй другой UnmanagedType



Попробовал LPWStr, LPTStr, LPStr. На последнем варианте крякозябры поменялись, и все равно ни на что не похожи. На других типах UnmanagedType прога ругается, что можно указывать только вышеуказанные типы.

277
02 февраля 2012 года
arrjj
1.7K / / 26.01.2011
Попробуй в dll явно вернуть строку например там "abсЭЮЯ" и посмотри что будет.
10K
02 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Цитата: arrjj
Попробуй в dll явно вернуть строку например там "abсЭЮЯ" и посмотри что будет.



Значит, вот что есть на данный момент после всех изменений:

DLL:

 
Код:
extern "C" __declspec(dllexport) void __stdcall GetTextResult(void* pAlgorithm,  wchar_t* resultString)
{
    //resultString = (wchar_t*)((AlgorithmDinamicProg*)pAlgorithm)->GetTextResult();
    resultString = L"abcЭЮЯ";
}


Объявление:
 
Код:
[DllImport("DinamicProg.dll", CharSet = CharSet.Unicode)]
private static extern void GetTextResult(IntPtr algorithmHandle, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder stringBuilder);


Использование:
 
Код:
StringBuilder stringBuilder = new StringBuilder();
GetTextResult(_algorithmHandler, stringBuilder);
ResultString = stringBuilder.ToString();


Результат:
Цитата:
ᾆ獛ᾎ獛씩օօ珌玭膐ɹօ飻

277
02 февраля 2012 года
arrjj
1.7K / / 26.01.2011
А StringBuilder просто как параметр укажи (без [Out, MarshalAs...)
И вот пример с мсдн.
20K
02 февраля 2012 года
sem2711
124 / / 23.09.2009
В .NET кодировка строк по умолчанию UTF-8, а в C++ wchar_t соответствует кодировке UTF-16. Может быть попробовать в C++ перевести строки в UTF-8 с помощью функции WideCharToMultiByte?
10K
03 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Цитата: sem2711
В .NET кодировка строк по умолчанию UTF-8, а в C++ wchar_t соответствует кодировке UTF-16. Может быть попробовать в C++ перевести строки в UTF-8 с помощью функции WideCharToMultiByte?



Стоп. Разве по умолчанию типа char в .NET не двубайтовый? (пруф раз и пруф два)
К слову, я только из-за этого в С++ сделал wchar_t.

10K
03 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Цитата: arrjj
А StringBuilder просто как параметр укажи (без [Out, MarshalAs...)
И вот пример с мсдн.


Никак :(
Получает пустую строку.
А может быть проблема в С++'коде? У меня есть возможность его менять. Может стоит воспользоваться виндовыми дейфайнами, и проводить мой результат к LPTSTR?

И еще момент. У меня в С++ коде можно видеть, что идет приведения результата моих внутренних процедур к wchar_t*. Идет это от const wchar_t*. В этом может быть проблема?

10K
03 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Цитата: arrjj
И вот пример с мсдн.


SUCCESS!!!

На втором методе, через указатель на участок памяти и IntPtr получилось!
Остается только гадать, почему не получилось сделать это напрямую.

Пока буду делать так, но если придумаете, как строку в явном виде получить, с интересом почитаю :)

10K
03 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Не успел нарадоваться. Хотел вернуть указатель строку через выходной параметр, а не return-выражение.

В результате код:
[CODE=C#][DllImport("MyLib.dll")]
private static extern int GetResult(IntPtr algorithmHandle, [Out] out IntPtr resultPointer);[/CODE]
на выходе дает нулевой указатель. В плюсах, как и раньше, на месте второго параметра стоит (void*). Пробовал еще делать так: [In, Out] ref IntPtr resultPointer, но исход тот же.
Что неправильно?
277
03 февраля 2012 года
arrjj
1.7K / / 26.01.2011
Цитата: Cybernetic

Остается только гадать, почему не получилось сделать это напрямую.


Потому что он пытается потом освободить память по указателю, чего ему не дают сделать :) Так что таким методом тебе нужно будет самому следить за освобождением памяти.

А первый метод не работает?

10K
03 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Цитата: arrjj
Потому что он пытается потом освободить память по указателю, чего ему не дают сделать :) Так что таким методом тебе нужно будет самому следить за освобождением памяти.


Да я бы не против самому следить за памятью, но он все равно мне либо ничего не возвращает, либо возвращает фигню. Хрен с не с памятью, хоть бы что-нибудь вернул =)

Цитата: arrjj
А первый метод не работает?


Не работает. В StringBuilder оказывается пустая строка.

10K
03 февраля 2012 года
Cybernetic
106 / / 22.07.2009
Цитата: arrjj
А первый метод не работает?


Если в плюсах использовать в параметре не wchar_t*, а wchar_t**, то в StringBuilder оказываются знакомые нам крякозябры. Лучше, чем пустая строка, но в целом не то =)

[QUOTE=Cybernetic]Не успел нарадоваться. Хотел вернуть указатель строку через выходной параметр, а не return-выражение.

В результате код:
[CODE=C#]
[DllImport("MyLib.dll")]
private static extern int GetResult(IntPtr algorithmHandle, [Out] out IntPtr resultPointer); [/CODE]
на выходе дает нулевой указатель. В плюсах, как и раньше, на месте второго параметра стоит (void*). Пробовал еще делать так: [In, Out] ref IntPtr resultPointer, но исход тот же.
Что неправильно?[/QUOTE]

Проблема решилась, когда вместо void* стал указывать void**.

20K
03 февраля 2012 года
sem2711
124 / / 23.09.2009
Цитата: Cybernetic
Стоп. Разве по умолчанию типа char в .NET не двубайтовый? (пруф раз и пруф два)
К слову, я только из-за этого в С++ сделал wchar_t.


Sorry, был не прав. Это запись в текстовый файл у соответствующих классов .NET по умолчанию в UTF-8 кодировке производится.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог