Ошибка преобразования VB6 в VB.NET, вызов функции для функции .dll возвращает ошибку - PullRequest
1 голос
/ 20 октября 2010

Я недавно преобразовал программу VB6 в VB.NET. Эта программа используется для связи с DAQ-картой Superlogics PCM Series, которую компания больше не производит и не поддерживает VB.NET. Моя программа работала нормально в VB6, но у нее проблемы в VB.net из-за функций во внешнем файле .dll (хотя я не уверен)

Я прочитал много форумов и сделал некоторые изменения в отношении атрибутов маршалинга. Так, ребята, пожалуйста, дайте мне ваши идеи для решения этой проблемы -

Error

'Я получаю сообщение об ошибке с intStatus = 350 (имеется в виду «Неверный дескриптор запроса»)

'Руководство по суперлогике просто просит меня проверить функцию PCMDigitalInputVB. Пожалуйста, помогите мне, спасибо заранее

Public Function singleDigitalInput(ByVal LogicalDevice As Short, ByVal Channel As Short, ByRef InputValue As Byte) As Long

    Dim intStatus As Short
    Dim intRequestHandle As Short
    Dim udtDigioRequest As New DigioRequest
    udtDigioRequest.Initialize()
    Dim udtDataBuffer As New PCMDriveBuffer
    Dim udtAllocateRequest As New allocate_request

    Dim lngRetChannelAdd As Integer
    Dim lngRetBufferAdd As Integer

    Dim blnCompleteStatus As Boolean
    Dim lngEventMask As Integer
    Dim ErrorCode As Short

    On Error GoTo errUnknown



    intRequestHandle = 0
    blnCompleteStatus = False

    '-------------------------------------------------------------------
    'Allocate and lock memory for the Digital Input
    '-------------------------------------------------------------------

    With udtAllocateRequest
        .request_type = DIGIN_TYPE_REQUEST
        .channel_array_length = 1
        .number_of_buffers = 1
        .buffer_size = 1
        .buffer_attributes = RING_BUFFER
    End With

    intStatus = PCMAllocateRequestVB(LogicalDevice, udtAllocateRequest)

    If intStatus <> 0 Then
        singleDigitalInput = intStatus
        Exit Function
    End If

    'Debug.Print "Allocate Request Status = " & intStatus

    '-------------------------------------------------------------------
    'Prepare the Digital Input Request Structure
    '-------------------------------------------------------------------

    lngRetChannelAdd = PCMGetAddressOfVB(Channel)
    'UPGRADE_WARNING: Couldn't resolve default property of object udtDataBuffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"'
    lngRetBufferAdd = PCMGetAddressOfVB(udtDataBuffer)

    With udtDigioRequest
        .ChannelArrayPtr = lngRetChannelAdd
        .ArrayLength = 1
        .DigioBufferptr = lngRetBufferAdd
        .NumberOfScans = 1
        .IOMode = ForegroundCPU
        .TriggerSource = InternalTrigger
        .ScanEventLevel = 0
        .RequestStatus = NoEvents
    End With

    '-------------------------------------------------------------------
    'Send a digital input request to the PCMDrive

'Я получаю сообщение об ошибке «Неверный дескриптор запроса» с intStatus = 350

'Руководство по суперлогике просит меня проверить функцию PCMDigitalInputVB и ничего более «------------------------------------------------- ------------------

    intStatus = PCMDigitalInputVB(LogicalDevice, udtDigioRequest, intRequestHandle)


End Function

'----- Объявление функции' ---------------

Declare Function PCMDigitalInputVB Lib "PCMDrvVB.DLL" (ByVal logical_device As Short, ByRef Request As DigioRequest, ByRef handle As Short) As Short

'------------ Объявление структуры -------------------------------- ---------

Structure DigioRequest
    Dim ChannelArrayPtr As Integer ' address of channel scan list
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> Dim ReservedArray0 As Short() ' reserved for future expansion
    Dim ArrayLength As Short ' length of chan & gain arrays
    Dim DigioBufferptr As Integer ' address of PCMDRIVE_buffer
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> Dim ReservedArray1 As Short() ' reserved for future expansion
    Dim TriggerSource As Short ' trigger source
    Dim TriggerMode As Short ' continuous / one-shot trigger
    Dim TriggerSlope As Short ' rising / falling edge trigger
    Dim TriggerChannel As Short ' trigger channel number
    '   (analog or digital trigger)
    Dim TriggerVoltage As Double ' trigger voltage (analog trigger)
    Dim TriggerValue As Integer ' value for trigger (digital trigger)
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> Dim ReservedArray2 As Short() ' reserved for future expansion
    Dim IOMode As Short ' input mode
    '    = 0 poll
    '    = 1 IRQ
    '    = 2 DMA with CPU status
    '    = 3 DMA with IRQ status
    Dim ClockSource As Short ' clock source (0 = internal)
    Dim ClockRate As Double ' clock rate (if not internal)
    Dim SampleRate As Double ' input sampling rate (Hz)
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> Dim ReservedArray3 As Short() ' reserved for future expansion
    Dim NumberOfScans As Integer ' number of channel scans
    Dim ScanEventLevel As Integer ' generate event each scan_event_level
    '    scans ( 0 = disable )
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=7)> Dim ReservedArray4 As Short() ' reserved for future expansion
    Dim TimeoutInterval As Short ' timeout interval (in sec)
    Dim RequestStatus As Integer ' request event status
    Public Sub Initialize()
        ReDim ReservedArray0(3)
        ReDim ReservedArray1(3)
        ReDim ReservedArray2(3)
        ReDim ReservedArray3(3)
        ReDim ReservedArray4(7)
    End Sub
End Structure

Ответы [ 2 ]

1 голос
/ 20 октября 2010

Поскольку код VB6 работает нормально, я просто преобразовал (обернул) соответствующий интерфейсный интерфейс в модуле класса VB6 и создал компонент COM (Новый проект> DLL ActiveX в VB6).
Полученная библиотека DLL можетвызываться из .NET с помощью COM Interop.
См. также этот вопрос SO для получения более подробной информации.

0 голосов
/ 20 октября 2010

Это похоже на проблему pInvoke. Это может быть довольно сложно. Как сказал предыдущий комментатор, вам может быть проще просто поместить существующий код в COM-компонент VB6 и вызвать его из своего проекта dotNet.

Однако, это должно быть выполнимо и из dotNet. Нужно иметь в виду, что это сборщик мусора. Любая переменная (включая UDT / структуры) может быть перемещена в память сборщиком мусора в любое время. Обычно это проявляется в том, что приложение иногда работает, но не в других случаях.

Если ошибка возникает каждый раз, дважды проверьте ваши объявления pInvoke для вызовов API и убедитесь, что вы используете правильные типы данных и размеры. Также убедитесь, что вы передаете параметры byval / byref соответственно.

Кроме того, эти проблемы трудно диагностировать без доступа к документации API или большого количества проб и ошибок.

...