VB6 AddressOf и обратные вызовы в VS 2008

Привет всем, я пытаюсь преобразовать некоторый код VB6 в VS 2008 с помощью его автоматического конвертера кода VB6. Большинство из них хорошо, но есть несколько, которые нуждаются в подкраске.

Один сказал, что ретушь — это фрагмент кода:

InitializeGrCap = GrCapInitialize(AddressOf GrCapStatusEventHandler)

И GrCapInitialize таков:

Public Declare Function GrCapInitialize Lib "GrFinger.dll" Alias "_GrCapInitialize@4" (ByVal StatusEventHandler As Integer) As Integer

И GrCapStatusEventHandler:

Public Sub GrCapStatusEventHandler(ByVal pidSensor As Integer, ByVal eventRaised As Integer)
    While fireStatus = True
        System.Windows.Forms.Application.DoEvents()
    End While

    myPIdSensor = pidSensor
    myEventRaised = eventRaised     
    fireStatus = True

    While fireStatus = True
        System.Windows.Forms.Application.DoEvents()
    End While
End Sub

Я не уверен, как переписать это, чтобы решить проблему:

Ошибка 44. Выражение «AddressOf» не может быть преобразовано в «Integer», поскольку «Integer» не является типом делегата.

Второй упомянутый штрих - это этот фрагмент кода:

GrCapStartCapture(myIdSensor, AddressOf GrCapFingerEventHandler, AddressOf GrCapImageEventHandler)

И опять же, AddressOf... — это ошибки в этом:

GrCapFingerEventHandler:

Public Sub GrCapFingerEventHandler(ByVal pidSensor As Integer, ByVal eventRaised As Integer)
    While fireFinger = True
        System.Windows.Forms.Application.DoEvents()
    End While

    myPIdSensor = pidSensor
    myEventRaised = eventRaised
    fireFinger = True

    While fireFinger = True
        System.Windows.Forms.Application.DoEvents()
    End While
End Sub

И GrCapImageEventHandler:

Public Sub GrCapImageEventHandler(ByVal pidSensor As Integer, ByVal width As Integer, ByVal height As Integer, ByVal pRawImage As Integer, ByVal res As Integer)
    While fireImage = True
        System.Windows.Forms.Application.DoEvents()
    End While

    myPIdSensor = pidSensor
    myWidth = width
    myHeight = height
    myRes = res
    myRawImage = pRawImage
    fireImage = True

    While fireImage = True
        System.Windows.Forms.Application.DoEvents()
    End While
End Sub

И снова ошибка:

Ошибка 44. Выражение «AddressOf» не может быть преобразовано в «Integer», поскольку «Integer» не является типом делегата.

Может ли кто-нибудь помочь мне преобразовать эти 2 области кода в .net?


person StealthRT    schedule 14.07.2017    source источник


Ответы (1)


В VB6 тот Integer, который вы передали своей неуправляемой функции, был бы указателем на функцию. VB.NET не использует указатели на функции. Вместо этого .NET использует делегаты, которые представляют собой объекты, ссылающиеся на методы. Это означает, что вам нужен тип делегата с сигнатурой, которая соответствует вашему управляемому методу, а затем вы можете объявить параметр вашей неуправляемой функции как этот тип и передать экземпляр этого типа при вызове этой функции. Вы можете объявить свой собственный тип делегата, например.

Public Delegate Sub GrCapStatusCallback(ByVal pidSensor As Integer, ByVal eventRaised As Integer)

объявите свою внешнюю функцию для использования этого типа:

Public Declare Function GrCapInitialize Lib "GrFinger.dll" Alias "_GrCapInitialize@4" (ByVal StatusEventHandler As GrCapStatusCallback) As Integer

и тогда вызов, который у вас есть, должен работать как есть, или вы можете явно создать экземпляр делегата:

InitializeGrCap = GrCapInitialize(New GrCapStatusCallback(AddressOf GrCapStatusEventHandler))

В качестве альтернативы вы можете использовать существующие делегаты Action и Func, которые предназначены для Subs и Functions соответственно и могут поддерживать от 0 до 16 параметров:

Public Declare Function GrCapInitialize Lib "GrFinger.dll" Alias "_GrCapInitialize@4" (ByVal StatusEventHandler As Action(Of Integer, Integer)) As Integer
person jmcilhinney    schedule 14.07.2017
comment
Спасибо за ответ, JM. Однако я по-прежнему получаю ту же ошибку при изменении его на InitializeGrCap = GrCapInitialize(New GrCapStatusCallback(AddressOf GrCapStatusEventHandler)) с ошибкой Error 1 Значение типа 'GrFingerSampleVB6.Callbacks.GrCapStatusCallback' не может быть преобразуется в "целое число". - person StealthRT; 14.07.2017
comment
Тогда вы не изменили объявление своего неуправляемого метода, о котором я специально говорил в своем ответе. - person jmcilhinney; 14.07.2017
comment
Ах жаль пропустил это. Как насчет 2-го вопроса, указанного в ОП? - person StealthRT; 14.07.2017
comment
Это та же проблема, поэтому вы решаете ее с помощью тех же шагов. - person jmcilhinney; 14.07.2017
comment
Но он вызывает не объявление функции, а подфункции (GrCapFingerEventHandler и GrCapImageEventHandler). - person StealthRT; 14.07.2017
comment
Это точно такая же ситуация, как и первая, поэтому вы выполняете точно такие же шаги, чтобы исправить это. Прочтите то, что я написал, и сделайте то, что написано. Вы уже сделали это один раз, поэтому нет причин, по которым вы не можете сделать это снова. Позвольте мне написать это еще раз, чтобы у вас не было оправданий: вы можете объявить свой собственный тип делегата; объявите свою внешнюю функцию для использования этого типа; создать экземпляр делегата явно. GrCapFingerEventHandler и GrCapImageEventHandler — это методы обратного вызова, для которых необходимо объявить типы делегатов. GrCapStartCapture — это метод, сигнатура которого должна использовать эти типы делегатов. - person jmcilhinney; 14.07.2017
comment
Хотя механика этого верна, его реализация может привести к исключению нулевой ссылки, если делегат, созданный в вызове метода GrCapInitialize, является сборщиком мусора. Вам необходимо сохранить ссылку на делегат, чтобы предотвратить его сбор. См. раздел Асинхронные операции, закрепление. дискуссия по этому поводу. Найдите в статье: приложение отвечает за то, чтобы каким-то образом продлить время жизни делегата до тех пор, пока не прекратятся вызовы из неуправляемого кода. - person TnTinMn; 14.07.2017