Класс или интерфейс как аргумент функции

Для неординарных вопросов. Если вы опытный программист, попавший в трудную ситуацию, — вам сюда.

Модератор: gaidar

Правила форума
Этот раздел не предназначен для того, чтобы вы адресовали свою проблему профессионалам.
Этот раздел предназначен для профессионалов, которые столкнулись с проблемой и не могут решить ее самостоятельно.
Если вы считаете себя профессионалом, а свою проблему сложной — вам сюда.
Если модератор посчитает, что вы ошиблись, то на первый раз он перенесет ваше сообщение в основной раздел без последствий для автора. Во второй раз тема будет закрыта, а автору будет выписано нарушение. В третий раз автор будет забанен.
Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Класс или интерфейс как аргумент функции

Сообщение Qwertiy » 26.06.2011 (Вс) 22:01

Здравствуйте!

Недавно, когда писал перебор окон, столклулся с тем, что, если функция описана как получающая аргумент типа List(Of IntPtr), то при её вызове выкидывается исключение Cannot marshal 'parameter #2': Generic types cannot be marshaled.. После замены на IList всё заработало.

Хотелось бы узнать больше о передаче параметров в функции (особенно WinApi) и других ситуациях, в которых важен факт того, класс или интерфейс указан в описании функции. Буду рад получить ссылки на статьи, книги или обсуждения. Сам ничего на эту тему не нашёл.

Код: Выделить всё
Module EnumWithInterfaseArgument
  Private Delegate Function WindowEnumerator(ByVal hwnd As IntPtr, ByVal lparam As IList) As Boolean

  Private Declare Function EnumWindows Lib "user32" Alias "EnumWindows" (ByVal lpEnumFunc As WindowEnumerator, ByVal lparam As IList) As Integer

  Private Function AddToList(ByVal hwnd As IntPtr, ByVal Result As IList) As Boolean
    Result.Add(hwnd)
    Return True
  End Function

  Public Function GetAllWindows() As List(Of IntPtr)
    Dim Result As New List(Of IntPtr)
    EnumWindows(AddressOf AddToList, Result)
    Return Result
  End Function
End Module

Module EnumWithClassArgument
  Private Delegate Function WindowEnumerator(ByVal hwnd As IntPtr, ByVal lparam As List(Of IntPtr)) As Boolean

  Private Declare Function EnumWindows Lib "user32" Alias "EnumWindows" (ByVal lpEnumFunc As WindowEnumerator, ByVal lparam As List(Of IntPtr)) As Integer

  Private Function AddToList(ByVal hwnd As IntPtr, ByVal Result As List(Of IntPtr)) As Boolean
    Result.Add(hwnd)
    Return True
  End Function

  Public Function GetAllWindows() As List(Of IntPtr)
    Dim Result As New List(Of IntPtr)
    EnumWindows(AddressOf AddToList, Result)
    Return Result
  End Function
End Module

Module Main
  Public Sub Main()
    Try
      EnumWithInterfaseArgument.GetAllWindows()
      MsgBox("Ready", MsgBoxStyle.Information, "EnumWithInterfaseArgument")
    Catch ex As Exception
      MsgBox(ex.Message, MsgBoxStyle.Critical, "EnumWithInterfaseArgument")
    End Try

    Try
      EnumWithClassArgument.GetAllWindows()
      MsgBox("Ready", MsgBoxStyle.Information, "EnumWithClassArgument")
    Catch ex As Exception
      MsgBox(ex.Message, MsgBoxStyle.Critical, "EnumWithClassArgument")
    End Try
  End Sub
End Module


PS: У меня есть некоторые сомнения по поводу выбора этого раздела форума. Надеюсь, что не ошибся.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Класс или интерфейс как аргумент функции

Сообщение FireFenix » 26.06.2011 (Вс) 22:38

WinAPI тут не причём, специфика среды разработки. Вроде PInvoke и COM Interop не поддерживают генерики

Вообще это дикое извращение передавать managet данные в managet код, через unmanaget API
Чем не угодило сделать List(Of IntPtr) глобальной переменной?
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.06.2011 (Вс) 22:52

FireFenix писал(а):WinAPI тут не причём, специфика среды разработки. Вроде PInvoke и COM Interop не поддерживают генерики

Насколько я понимаю, дело в том, что WinApi - это unmanaged код, поэтому такая проблема и возникла.
Необходимость использовать какой-либо другой неуправляемый код у меня пока не возникала.

FireFenix писал(а):Вообще это дикое извращение передавать managet данные в managet код, через unmanaget API
Чем не угодило сделать List(Of IntPtr) глобальной переменной?

Тот код, который я привёл - это просто демонстрационный пример. А так, мне не хотелось использовать глобальную переменную в связи с тем, что такой же метод используется для получения дочерних окон.
Вообще, я руководствовался логикой, что в любом случае реально передаётся указатель. Сначала пытался поменять ByVal на ByRef - не помогло. Тогда заменил на интерфейс. Если честно, до сих пор не понимаю, в чём разница в логике передачи, поэтому и попросил что-нибудь почитать на эту тему.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Класс или интерфейс как аргумент функции

Сообщение FireFenix » 27.06.2011 (Пн) 1:08

Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 27.06.2011 (Пн) 1:37

FireFenix писал(а):msdn?

Спасибо. Посмотрю. На первый взгляд кажется, что тема правильная, но что-то не видно там того, что я ищу... Хотя, вполне возможно, что плохо смотрел.


Вернуться в Раздел для Профессионалов

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10

    TopList  
cron