How to use a dll written for VB.Net in C#

后端 未结 3 1180
无人共我
无人共我 2021-01-26 07:53

I have question to ask.

I have a dll file written for reading&writing data on USB. To use dll in VB.Net, one needs to integrate a .vb file which interface to that dl

相关标签:
3条回答
  • 2021-01-26 08:24

    You have a coupling problem in your design. To deal with this problem, I would recommend the following:

    • Turn HIDDLLInterface into a class that takes an IntPtr in the constructor. In the constructor, call hidConnect.
    • Make the class implement IDisposable. The VB IDE gives a decent default implementation. Because you are dealing with unmanaged resources, you should probably also uncomment the finalizer it adds.
    • Instead of calling form methods from the dll interface, raise events when the corresponding messages come in.
    • Check your PInvoke signatures. If an argument has "handle" in the name, or is declared in the native dll as HWND or Hsomething, you should use IntPtr instead of Integer to more closely match the meaning of the argument.
    • You may also consider providing additional method on the new class and completely encapsulate all of the "Declare" functions in the class, but that would be beyond the scope of this question.

    After that, the class should look something like this:

    Public Class HIDController
        Implements IDisposable
    
    #Region "Constructor"
        Public Sub New(handle As IntPtr)
            If Not hidConnect(handle) Then
                'consider a custom exception type here.  You may also get
                'more info about the failure from GetLastError.
                Throw New Exception("Connection failed")
            End If
            _handle = handle
            _prevWinProc = DelegateSetWindowLong(handle, GWL_WNDPROC, AddressOf Me.WinProc)
        End Sub
    #End Region
    #Region "IDisposable Support"
        Private disposedValue As Boolean 
        Protected Overridable Sub Dispose(disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                    ' TODO: dispose managed state (managed objects).
                End If
    
                ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
                DisconnectFromHID()
            End If
            Me.disposedValue = True
        End Sub
    
        Protected Overrides Sub Finalize()
            Dispose(False)
            MyBase.Finalize()
        End Sub
    
        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
    #End Region
    
        Private _handle As IntPtr
        Private ReadOnly _prevWinProc As IntPtr
    
        'on one hand, you are not supposed to throw from Dispose/Finalize, but
        'on the other hand, I don't know what you would do instead to signal failure.
        Private Sub DisconnectFromHID()
            'do not disconnect if you did not connect
            If _handle = IntPtr.Zero Then Exit Sub
    
            If Not hidDisconnect() Then
                'see above about custom exception type
                Throw New Exception("Disconnect failed")
            End If
            SetWindowLong(_handle, GWL_WNDPROC, _prevWinProc)
            _handle = IntPtr.Zero
        End Sub
    
        Private Function WinProc(ByVal pHWnd As IntPtr, ByVal pMsg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
            If pMsg = WM_HID_EVENT Then
                Select Case wParam.ToInt32()
                    Case NOTIFY_PLUGGED
                        OnPlugged(lParam)
                    Case NOTIFY_UNPLUGGED
                        OnUnplugged(lParam)
                    Case NOTIFY_CHANGED
                        OnChanged()
                    Case NOTIFY_READ
                        OnRead(lParam)
                End Select
            End If
    
            WinProc = CallWindowProc(FPrevWinProc, pHWnd, pMsg, wParam, lParam)
        End Function
    
    #Region "USB events"
        Private Sub OnPlugged(lParam As IntPtr)
            RaiseEvent Plugged(Me, New ParamEventArgs(lParam))
        End Sub
        Public Event Plugged As EventHandler(Of ParamEventArgs)
    
        Private Sub OnUnplugged(lParam As IntPtr)
            RaiseEvent Unplugged(Me, New ParamEventArgs(lParam))
        End Sub
        Public Event Unplugged As EventHandler(Of ParamEventArgs)
    
        Private Sub OnChanged()
            RaiseEvent Changed(Me, EventArgs.Empty)
        End Sub
        Public Event Changed As EventHandler
    
        Private Sub OnRead(lParam As IntPtr)
            RaiseEvent Read(Me, New ParamEventArgs(lParam))
        End Sub
        Public Event Read As EventHandler(Of ParamEventArgs)
    #End Region
    
        'other constants and declarations I did not copy.
    
    End Class
    
    Public Class ParamEventArgs
        Inherits EventArgs
    
        Public Sub New(param As IntPtr)
            _param = param
        End Sub
    
        Private _param As IntPtr
        Public ReadOnly Property Param() As IntPtr
            Get
                Return _param
            End Get
        End Property
    
    End Class
    

    From there, you can change your form to create and dispose an instance of this class in the Load/Close events and hook the handlers. You will have to change your form methods to match the event signatures, but this should be straightforward.

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        _controller = new HIDController(Me.Handle)
        AddHandler _controller.Plugged, AddressOf Me.OnPlugged
        'similarly for other events
    End Sub
    
    Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        If _controller IsNot Nothing Then _controller.Dispose()
    End Sub
    

    Now the class should be simple to use from a C# dll. Simply compile the HIDController into an assembly in VB.NET and then reference that dll from your C# project (and import any needed namespace). Don't forget to copy the native dll as well; the C# compiler will only copy the VB dll automatically. Any class that can provide a window handle can now create the HIDController and handle its events without the controller knowing which class is hosting it.

    PS: I would recommend turning on Option Strict when coding in VB. Also, you may want to look into DllImport for importing functions from native libraries into .NET projects, as that is how most examples will be and will make it easier to copy between VB and C#.

    0 讨论(0)
  • 2021-01-26 08:27

    Reference the C# dll in the VB project (or just drop the dll into the /bin folder)

    As you know, you need to adapt the VB.NET code in the form class to C#.

    In Answer to your question instead of a call from VB.NET Form codebehind:

    iConnectToHID(Me)
    

    You would use

    iConnectToHID(this);
    
    0 讨论(0)
  • 2021-01-26 08:29

    Assuming the VB.NET code is CLS compliant, you can simply add a reference to it to your C# project.

    At this point, the namespace and all public members in the DLL will be available to your C# code.

    0 讨论(0)
提交回复
热议问题