Комментарии 50
«Что меня всегда раздражало в библиотеке WS2 — так это способы возвращения ошибок, и чтения информации.»
Если вы не знали, хотел бы заметить, что такой способ обработки ошибок — это специфика WinAPI. В нем все (или большинство) функции возвращают коды ошибок, в том числе через HRESULT, 0, -1… Ну а GetLastError — это вовсе как раз системная функция созданная для того, чтобы понять что собственно произошло.
Собственно, переход на обработку ошибок через исключения — это одно из ключевых особенностей платформы .net. В момент выхода этот момент широко рекламировался, позиционировался как решение проблемы разнообразия и бардака с кодами ошибок.
* если вы это знали, то, надеюсь, информация пригодится тем, кто не знал
Если вы не знали, хотел бы заметить, что такой способ обработки ошибок — это специфика WinAPI. В нем все (или большинство) функции возвращают коды ошибок, в том числе через HRESULT, 0, -1… Ну а GetLastError — это вовсе как раз системная функция созданная для того, чтобы понять что собственно произошло.
Собственно, переход на обработку ошибок через исключения — это одно из ключевых особенностей платформы .net. В момент выхода этот момент широко рекламировался, позиционировался как решение проблемы разнообразия и бардака с кодами ошибок.
* если вы это знали, то, надеюсь, информация пригодится тем, кто не знал
+3
Хм, ну, это да, я это знаю и испытал на собственном горбу не раз 8-)
Не против, если я добавлю эту информацию в статью? 8-)
Не против, если я добавлю эту информацию в статью? 8-)
0
НЛО прилетело и опубликовало эту надпись здесь
согласный, но ключевое слово здесь «исключительные» ситуации, когда они случаются, то скорость уже отходит на несколько другой план
тут, как и везде, и лекарство и яд — все зависит от дозы и того как программист использует механизм
тут, как и везде, и лекарство и яд — все зависит от дозы и того как программист использует механизм
+2
Действительно, если заниматься тем, что оборачивать всю программу в try catch — это уже не серьёзно. Ещё более несерьёзно — передавать сообщения исключениями (Такое тоже было, некоторые люди так выходили из десятков вложенных циклов.)
А если у нас по исключению рухнул удалённый сервер — можно уже не торопиться. Сервер лежит, скорость не важна 8-)
А если у нас по исключению рухнул удалённый сервер — можно уже не торопиться. Сервер лежит, скорость не важна 8-)
+1
«Исключения — штука весьма медлительная» — при возникновении с вероятностью 1/100000 это не серьезно, а если у вас исключения 1/2 то значит что код кривой ))) хардом орехи не колим
«В итоге, работа с сокетами превратилась в песню» — буду критичен, как SDM заявляю что код отвратительный.
1. Цикломатичен
2. Смысла в try/catch никакого
3. Дублирование
4. Неверный
Замечания по статье:
.NET Socket в конечном итоге также вызывает функции winsock, с чего вы решили что ваша реализация лучше?
«В итоге, работа с сокетами превратилась в песню» — буду критичен, как SDM заявляю что код отвратительный.
1. Цикломатичен
2. Смысла в try/catch никакого
3. Дублирование
4. Неверный
Замечания по статье:
.NET Socket в конечном итоге также вызывает функции winsock, с чего вы решили что ваша реализация лучше?
-1
Для pinvoke в .NET есть замечательная функция — Marshal.GetLastWin32Error(), при получении нативной ошибки в pinvoke брать результат нужно именно ей, а не обёрткой над нативной GetLastError() :-)
* это так, если кто не знал
* это так, если кто не знал
+2
Хммм… Спасибо, вот этого не знал 8-)
0
Если дергаете функции WinSock то желательно получать ошибку с помощью обертки над WSAGetLastError(), проверено на опыте.
0
В атрибуте 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 непосредственно.
0
> Ну, можно попытаться ускорить ваше приложение, используя вычисления на очень сложном и быстром Assembler'е.
Только предварительно прикинуть, покроет ли «сложный и быстрый ассемблер» затраты на P/Invoke и не создаст ли это дофига дополнительных проблем с разрядностью native-кода.
Только предварительно прикинуть, покроет ли «сложный и быстрый ассемблер» затраты на P/Invoke и не создаст ли это дофига дополнительных проблем с разрядностью native-кода.
0
Как показала практика WPF, который для рендеринга контролов использует нативные методы работы с DirectX — всё не так плохо.
+1
С чего вы взяли, что он использует для этого p/invoke? Для этого есть более подходящие методы.
0
Спасибо, мне это известно.
Вопрос был о том, с чего вы решили, что для вызова анменеджеда используется p/invoke?
Вопрос был о том, с чего вы решили, что для вызова анменеджеда используется p/invoke?
0
Пинвок — это технология межпрограммного взаимодействия. Через что именно она работает в милкоре — это ещё надо поискать 8-). Факт в том, что она там есть, хотя не факт, что на Дллиморте.
0
В лучших традициях велосипедостроения :))
В .net платформе реализован доступ практически ко всем ф-циям, в очень удобном виде. Для сокетов в свою очередь есть socket
Показать пример Interop людям, это конечно хорошо, но следовало бы показать там, где это действительно нужно, в 99% случаев в этом нет необходимости.
В .net платформе реализован доступ практически ко всем ф-циям, в очень удобном виде. Для сокетов в свою очередь есть socket
Показать пример Interop людям, это конечно хорошо, но следовало бы показать там, где это действительно нужно, в 99% случаев в этом нет необходимости.
-1
Я об этом упоминал всю статью 8-) Это — пример, который показывает, как реализовывать. Другое дело, что сокеты — это всегда интересно и прикольно.
+1
Согласен по-поводу 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);
}
}
}
+1
Да, ну и неплохо бы привести в порядок чарсеты, а то там полная каша.
0
В смысле? Вы про конечный проект? Мы просто сделали просто. Мы добавили в списки все чарсэты, поддерживаемые конечной системой.
0
Вот ещё на примере работы с процессами — www.codeplex.com/PsInterop
+1
НЛО прилетело и опубликовало эту надпись здесь
А как побеждали тормоза с постоянным переключением managed/unmanaged? unsafe?
0
тут проблема в основном из-за маршалинга параметров и результата. к примеру строк или байтовых массивов, т.к. данные обычно копируются в/из манадж памяти. если дергаете void Method() то особых тормозов не будет :)
0
Скажем так, на текущих объёмах у нас вообще не было тормозов. Они не могли появиться при таком раскладе.
0
итог какой статьи? на сколько быстро ипользовать winapi через этот кошмар чем использовать существующие обертки в .net?
0
Статьи итог такой: не под всё есть обёртки, иногда надо кошмарить.
0
ну тогда пример плохой, так как это можно сделать уже существующими обертками.
Было супер имено посмотреть сравнение насколько быстро был написан код на том или на том. и на сколько быстро работает то или иное. а так статья получается просто про то как вызвать с/c++ библиотеку из .net
Было супер имено посмотреть сравнение насколько быстро был написан код на том или на том. и на сколько быстро работает то или иное. а так статья получается просто про то как вызвать с/c++ библиотеку из .net
0
btw, недавно писал про альтернативный метод интеропа с .NET через C++/CLI — habrahabr.ru/blogs/programming/47732/
здорово помогает, когда надо C++-код обернуть
а иногда просто лень с настройкой маршаллинга в P/Invoke возиться, делаю тонкую обертку с .NET-интерфейсом прямо на C++/CLI
здорово помогает, когда надо C++-код обернуть
а иногда просто лень с настройкой маршаллинга в P/Invoke возиться, делаю тонкую обертку с .NET-интерфейсом прямо на C++/CLI
+1
А вы молодец, хорошую статью написали. Сам помню так же велосипедили года 2 назад, когда у нас сети были :).
Только я потом узнал, что .Net sockets очень медленные, особенно когда они используются асинхронно. Посему если критична скорость, то лучше написать свою обёртку, только писать её нужно эээ… немножко… подругому ;).
Только я потом узнал, что .Net sockets очень медленные, особенно когда они используются асинхронно. Посему если критична скорость, то лучше написать свою обёртку, только писать её нужно эээ… немножко… подругому ;).
+1
Машинный код .NET и машинный код Native (Не-.NET) приложений это не одно и то же. Соответственно, выходит интересная штука: мы можем взять одно Native приложение, написанное на языке Assembler, и взять другое Native приложение, написанное я языке Pascal, и скрестить их вместе.
Как-то я не понял логический переход:) Можно пояснить?
Как-то я не понял логический переход:) Можно пояснить?
+1
Два предложения. Каждое логически обособленно. Такое бывает с предложениями. 8-)
0
Что занчит машинный код .Net? IL? Так это не машинный код. Машинным он становится только после jit-компиляции.
Мы долго искали компромиссы с нашим преподом, и в итоге пришли к следующему: Нам позволяют использовать .NET при условии, что WS2 мы будем дёргать через DllImport.
Препод идиот, хотя в этом ничего удивительного. Как по его мнению System.Net.Sockets.Socket работает?
Эх были времена… Помню как мы уламывали препода на лабах, чтоб писать на С++, а не на фортране.
Мы долго искали компромиссы с нашим преподом, и в итоге пришли к следующему: Нам позволяют использовать .NET при условии, что WS2 мы будем дёргать через DllImport.
Препод идиот, хотя в этом ничего удивительного. Как по его мнению System.Net.Sockets.Socket работает?
Эх были времена… Помню как мы уламывали препода на лабах, чтоб писать на С++, а не на фортране.
-1
Очень интересная мысль про скрещивание с# и с. Вот предположим, есть железка — трекер, она программируется на с. Интересно, возможно ли написать управляющий код на c#, который компоновал бы инструкции С таким образом, чтобы получалась полноценная, работающая программа на с? Которую, в конечном итоге, можно было бы залить программатором в железку?
+1
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
.NET Interop на примере работы с сокетами