1

最近、VB6 プログラムを VB.NET に変換しました。このプログラムは、Superlogics PCM シリーズ DAQ カードと通信するために使用されます。このカードは、同社が生産を終了し、VB.NET をサポートしていません。私のプログラムは VB6 では問題なく動作していましたが、VB.net では外部の .dll ファイルの関数が原因で問題が発生しました (よくわかりません)。

多くのフォーラムを読み、マーシャリング属性に関していくつかの変更を行いました。皆さん、これを解決するためのアイデアを教えてください -

エラー

'intStatus = 350 のエラーが発生しました (「無効なリクエスト ハンドル」を参照)

'superlogics のマニュアルでは、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 の「無効なリクエスト ハンドル」というエラーが表示されます

'superlogics のマニュアルでは、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
4

2 に答える 2

1

VB6 コードはそのままで問題なく動作するので、関連するインターフェイス コードを VB6 クラス モジュールに変換 (ラップ) し、COM コンポーネントを作成します (VB6 の [新しいプロジェクト] > [ActiveX DLL])。
結果の COM DLL は、COM Interop を使用して .NET から呼び出すことができます。
詳細については、この SO の質問も参照してください。

于 2010-10-20T05:37:39.553 に答える
0

これはpInvokeの問題のようです。これらは非常にイライラする可能性があります。前のコメント投稿者が言ったように、既存のコードをVB6 COMコンポーネントにラップし、それをdotNetプロジェクトから呼び出す方が簡単かもしれません。

ただし、dotNetからも実行できるはずです。覚えておくべきことの1つは、ガベージコレクターです。任意の変数(UDT /構造体を含む)は、ガベージコレクターによっていつでもメモリ内で移動できます。通常、これはアプリが機能していることを示しますが、そうでない場合もあります。

エラーが毎回発生する場合は、API呼び出しのpInvoke宣言を再確認し、正しいデータ型とサイズを使用していることを確認してください。また、パラメータbyval/byrefを適切に渡していることを確認してください。

それ以外は、APIドキュメントへのアクセスや多くの試行錯誤なしに、これらの問題を診断することは困難です。

于 2010-10-20T06:00:43.923 に答える