Комментарии 50
«Что меня всегда раздражало в библиотеке WS2 — так это способы возвращения ошибок, и чтения информации.»
Если вы не знали, хотел бы заметить, что такой способ обработки ошибок — это специфика WinAPI. В нем все (или большинство) функции возвращают коды ошибок, в том числе через HRESULT, 0, -1… Ну а GetLastError — это вовсе как раз системная функция созданная для того, чтобы понять что собственно произошло.
Собственно, переход на обработку ошибок через исключения — это одно из ключевых особенностей платформы .net. В момент выхода этот момент широко рекламировался, позиционировался как решение проблемы разнообразия и бардака с кодами ошибок.
* если вы это знали, то, надеюсь, информация пригодится тем, кто не знал
Если вы не знали, хотел бы заметить, что такой способ обработки ошибок — это специфика WinAPI. В нем все (или большинство) функции возвращают коды ошибок, в том числе через HRESULT, 0, -1… Ну а GetLastError — это вовсе как раз системная функция созданная для того, чтобы понять что собственно произошло.
Собственно, переход на обработку ошибок через исключения — это одно из ключевых особенностей платформы .net. В момент выхода этот момент широко рекламировался, позиционировался как решение проблемы разнообразия и бардака с кодами ошибок.
* если вы это знали, то, надеюсь, информация пригодится тем, кто не знал
Хм, ну, это да, я это знаю и испытал на собственном горбу не раз 8-)
Не против, если я добавлю эту информацию в статью? 8-)
Не против, если я добавлю эту информацию в статью? 8-)
согласный, но ключевое слово здесь «исключительные» ситуации, когда они случаются, то скорость уже отходит на несколько другой план
тут, как и везде, и лекарство и яд — все зависит от дозы и того как программист использует механизм
тут, как и везде, и лекарство и яд — все зависит от дозы и того как программист использует механизм
Действительно, если заниматься тем, что оборачивать всю программу в try catch — это уже не серьёзно. Ещё более несерьёзно — передавать сообщения исключениями (Такое тоже было, некоторые люди так выходили из десятков вложенных циклов.)
А если у нас по исключению рухнул удалённый сервер — можно уже не торопиться. Сервер лежит, скорость не важна 8-)
А если у нас по исключению рухнул удалённый сервер — можно уже не торопиться. Сервер лежит, скорость не важна 8-)
«Исключения — штука весьма медлительная» — при возникновении с вероятностью 1/100000 это не серьезно, а если у вас исключения 1/2 то значит что код кривой ))) хардом орехи не колим
«В итоге, работа с сокетами превратилась в песню» — буду критичен, как SDM заявляю что код отвратительный.
1. Цикломатичен
2. Смысла в try/catch никакого
3. Дублирование
4. Неверный
Замечания по статье:
.NET Socket в конечном итоге также вызывает функции winsock, с чего вы решили что ваша реализация лучше?
«В итоге, работа с сокетами превратилась в песню» — буду критичен, как SDM заявляю что код отвратительный.
1. Цикломатичен
2. Смысла в try/catch никакого
3. Дублирование
4. Неверный
Замечания по статье:
.NET Socket в конечном итоге также вызывает функции winsock, с чего вы решили что ваша реализация лучше?
Для pinvoke в .NET есть замечательная функция — Marshal.GetLastWin32Error(), при получении нативной ошибки в pinvoke брать результат нужно именно ей, а не обёрткой над нативной GetLastError() :-)
* это так, если кто не знал
* это так, если кто не знал
Хммм… Спасибо, вот этого не знал 8-)
Если дергаете функции WinSock то желательно получать ошибку с помощью обертки над WSAGetLastError(), проверено на опыте.
В атрибуте DllImport есть параметр SetLastError. Пример из MSDN:
[DllImport(«user32.dll», SetLastError=true)]
public static extern int MessageBoxA(int hWnd, String text, String caption, uint type);
После вызова функции маршаллер вызовет winapi-функцию GetLastError и сохранит возвращённое значение. Потом его можно будет получить через Marshal.GetLastWin32Error.
MSDN говорит, что значение по умолчанию — false. Возможно, если оно false, то GetLastWin32Error будет не возвращать сохранённое значение, а вызывать GetLastError непосредственно.
[DllImport(«user32.dll», SetLastError=true)]
public static extern int MessageBoxA(int hWnd, String text, String caption, uint type);
После вызова функции маршаллер вызовет winapi-функцию GetLastError и сохранит возвращённое значение. Потом его можно будет получить через Marshal.GetLastWin32Error.
MSDN говорит, что значение по умолчанию — false. Возможно, если оно false, то GetLastWin32Error будет не возвращать сохранённое значение, а вызывать GetLastError непосредственно.
> Ну, можно попытаться ускорить ваше приложение, используя вычисления на очень сложном и быстром Assembler'е.
Только предварительно прикинуть, покроет ли «сложный и быстрый ассемблер» затраты на P/Invoke и не создаст ли это дофига дополнительных проблем с разрядностью native-кода.
Только предварительно прикинуть, покроет ли «сложный и быстрый ассемблер» затраты на P/Invoke и не создаст ли это дофига дополнительных проблем с разрядностью native-кода.
Как показала практика WPF, который для рендеринга контролов использует нативные методы работы с DirectX — всё не так плохо.
С чего вы взяли, что он использует для этого p/invoke? Для этого есть более подходящие методы.
Спасибо, мне это известно.
Вопрос был о том, с чего вы решили, что для вызова анменеджеда используется p/invoke?
Вопрос был о том, с чего вы решили, что для вызова анменеджеда используется p/invoke?
Пинвок — это технология межпрограммного взаимодействия. Через что именно она работает в милкоре — это ещё надо поискать 8-). Факт в том, что она там есть, хотя не факт, что на Дллиморте.
В лучших традициях велосипедостроения :))
В .net платформе реализован доступ практически ко всем ф-циям, в очень удобном виде. Для сокетов в свою очередь есть socket
Показать пример Interop людям, это конечно хорошо, но следовало бы показать там, где это действительно нужно, в 99% случаев в этом нет необходимости.
В .net платформе реализован доступ практически ко всем ф-циям, в очень удобном виде. Для сокетов в свою очередь есть socket
Показать пример Interop людям, это конечно хорошо, но следовало бы показать там, где это действительно нужно, в 99% случаев в этом нет необходимости.
Я об этом упоминал всю статью 8-) Это — пример, который показывает, как реализовывать. Другое дело, что сокеты — это всегда интересно и прикольно.
Согласен по-поводу 99%. Мне редко вообще приходилось этим пользоваться. Например, необходимо было в OpenFileDalog отображать эскизы страниц, что оказалось не реализуемо средствами.нет, вот пришлось использовать Interop.
[DllImport(«user32.dll», EntryPoint=«SendMessageA», CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
private static extern uint SendMessage(uint Hdc, uint Msg_Const, uint wParam, uint lParam);
[DllImport(«user32.dll», EntryPoint=«FindWindowExA», CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
private static extern uint FindWindowEx(uint hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow); [DllImport(«user32.dll»,EntryPoint=«GetForegroundWindow»,CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)] private static extern uint GetForegroundWindow();
private void ThumbNailActiveWindow()
{
lock(this)
{
uint listviewHandle = 0;
while(listviewHandle == 0 && isWatching)
{
listviewHandle = FindWindowEx(GetForegroundWindow(), 0, «SHELLDLL_DefView», "");
}
if(listviewHandle != 0)
{
SendMessage(listviewHandle, WM_COMMAND, 0x702d, 0);
}
}
}
[DllImport(«user32.dll», EntryPoint=«SendMessageA», CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
private static extern uint SendMessage(uint Hdc, uint Msg_Const, uint wParam, uint lParam);
[DllImport(«user32.dll», EntryPoint=«FindWindowExA», CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
private static extern uint FindWindowEx(uint hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow); [DllImport(«user32.dll»,EntryPoint=«GetForegroundWindow»,CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)] private static extern uint GetForegroundWindow();
private void ThumbNailActiveWindow()
{
lock(this)
{
uint listviewHandle = 0;
while(listviewHandle == 0 && isWatching)
{
listviewHandle = FindWindowEx(GetForegroundWindow(), 0, «SHELLDLL_DefView», "");
}
if(listviewHandle != 0)
{
SendMessage(listviewHandle, WM_COMMAND, 0x702d, 0);
}
}
}
Да, ну и неплохо бы привести в порядок чарсеты, а то там полная каша.
В смысле? Вы про конечный проект? Мы просто сделали просто. Мы добавили в списки все чарсэты, поддерживаемые конечной системой.
Вот ещё на примере работы с процессами — www.codeplex.com/PsInterop
А как побеждали тормоза с постоянным переключением managed/unmanaged? unsafe?
тут проблема в основном из-за маршалинга параметров и результата. к примеру строк или байтовых массивов, т.к. данные обычно копируются в/из манадж памяти. если дергаете void Method() то особых тормозов не будет :)
Скажем так, на текущих объёмах у нас вообще не было тормозов. Они не могли появиться при таком раскладе.
итог какой статьи? на сколько быстро ипользовать winapi через этот кошмар чем использовать существующие обертки в .net?
Статьи итог такой: не под всё есть обёртки, иногда надо кошмарить.
ну тогда пример плохой, так как это можно сделать уже существующими обертками.
Было супер имено посмотреть сравнение насколько быстро был написан код на том или на том. и на сколько быстро работает то или иное. а так статья получается просто про то как вызвать с/c++ библиотеку из .net
Было супер имено посмотреть сравнение насколько быстро был написан код на том или на том. и на сколько быстро работает то или иное. а так статья получается просто про то как вызвать с/c++ библиотеку из .net
btw, недавно писал про альтернативный метод интеропа с .NET через C++/CLI — habrahabr.ru/blogs/programming/47732/
здорово помогает, когда надо C++-код обернуть
а иногда просто лень с настройкой маршаллинга в P/Invoke возиться, делаю тонкую обертку с .NET-интерфейсом прямо на C++/CLI
здорово помогает, когда надо C++-код обернуть
а иногда просто лень с настройкой маршаллинга в P/Invoke возиться, делаю тонкую обертку с .NET-интерфейсом прямо на C++/CLI
А вы молодец, хорошую статью написали. Сам помню так же велосипедили года 2 назад, когда у нас сети были :).
Только я потом узнал, что .Net sockets очень медленные, особенно когда они используются асинхронно. Посему если критична скорость, то лучше написать свою обёртку, только писать её нужно эээ… немножко… подругому ;).
Только я потом узнал, что .Net sockets очень медленные, особенно когда они используются асинхронно. Посему если критична скорость, то лучше написать свою обёртку, только писать её нужно эээ… немножко… подругому ;).
Машинный код .NET и машинный код Native (Не-.NET) приложений это не одно и то же. Соответственно, выходит интересная штука: мы можем взять одно Native приложение, написанное на языке Assembler, и взять другое Native приложение, написанное я языке Pascal, и скрестить их вместе.
Как-то я не понял логический переход:) Можно пояснить?
Как-то я не понял логический переход:) Можно пояснить?
Два предложения. Каждое логически обособленно. Такое бывает с предложениями. 8-)
Что занчит машинный код .Net? IL? Так это не машинный код. Машинным он становится только после jit-компиляции.
Мы долго искали компромиссы с нашим преподом, и в итоге пришли к следующему: Нам позволяют использовать .NET при условии, что WS2 мы будем дёргать через DllImport.
Препод идиот, хотя в этом ничего удивительного. Как по его мнению System.Net.Sockets.Socket работает?
Эх были времена… Помню как мы уламывали препода на лабах, чтоб писать на С++, а не на фортране.
Мы долго искали компромиссы с нашим преподом, и в итоге пришли к следующему: Нам позволяют использовать .NET при условии, что WS2 мы будем дёргать через DllImport.
Препод идиот, хотя в этом ничего удивительного. Как по его мнению System.Net.Sockets.Socket работает?
Эх были времена… Помню как мы уламывали препода на лабах, чтоб писать на С++, а не на фортране.
Очень интересная мысль про скрещивание с# и с. Вот предположим, есть железка — трекер, она программируется на с. Интересно, возможно ли написать управляющий код на c#, который компоновал бы инструкции С таким образом, чтобы получалась полноценная, работающая программа на с? Которую, в конечном итоге, можно было бы залить программатором в железку?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
.NET Interop на примере работы с сокетами