Vb.net dll problems

Post questions and issues with Concept2 PM3 SDK
Post Reply
James Ball
Paddler
Posts: 3
Joined: January 27th, 2015, 6:33 am

Vb.net dll problems

Post by James Ball » February 12th, 2015, 9:23 am

I am creating a vb.net project that will connect to multiple ergs and display their data on a screen. Unfortunately I am having trouble connecting to the dlls and using the various functions in them. I am able to initialise the DDI dll using the following code:

Code: Select all

    Dim Error_Message As Integer
    Dim Start_Address As Integer
    Dim Num_Units As Integer
    Dim Product_Name As String

Private Declare Function Init Lib "PM3DDICP.dll" Alias "tkcmdsetDDI_init" () As Integer

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        TextBox1.Text = 999
        Refresh()
        Error_Message = Init()
        If Error_Message = 0 Then
            TextBox2.Text = "Init 0k!"
            TextBox1.Text = Error_Message
        Else
            TextBox2.Text = "Init Error!"
            TextBox1.Text = Error_Message
        End If
        Refresh()
    End Sub
This works fine and returns 0 as the error code, but when I try to do the discover_pm3s it comes up with this error:

An unhandled exception of type 'System.AccessViolationException' occurred in DLLTest.exe

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Here is the code for the discover_pm3s call:

Code: Select all

    <DllImportAttribute("PM3DDICP.dll", EntryPoint:="tkcmdsetDDI_discover_pm3s",
    SetLastError:=True, CharSet:=CharSet.Unicode,
    ExactSpelling:=True,
    CallingConvention:=CallingConvention.Cdecl)>
    Public Shared Function Discover_PM3s(ByVal Product_Name As String, ByVal Start_Address As Integer, Num_Units As Integer) As Integer
        ' This function gives the number of pm3s connected to the computer. 
        ' Leave this function empty. The DLLImport attribute forces calls 
        ' to Discover_PM3s to be forwarded to tkcmdsetDDI_discover_pm3s in PM3DDICP.DLL. 
    End Function

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Error_Message = Discover_PM3s(Product_Name, 0, Num_Units)
        TextBox1.Text = 999
        Refresh()
        If Error_Message = 0 Then
            TextBox2.Text = "0k!"
            TextBox1.Text = Error_Message
        Else
            TextBox2.Text = "Error!"
            TextBox1.Text = Error_Message
        End If
        Refresh()
    End Sub
I did have a different call for the discover_pm3s, but I realised that the calling convention is Cdecl not stdcall and therefore this wouldn't work:

Code: Select all

Private Declare Function Discover_PM3s Lib "PM3DDICP.dll" Alias "tkcmdsetDDI_discover_pm3s" (ByVal Product_Name As String, ByVal Start_Address As Integer, Num_Units As Integer) As Integer
Could someone please advise on what I should do to fix these errors, I thought I might have to write a wrapper dll to change the calling convention, or that it might be the mangling of the function names due to the C/C++ differences. Any help would be appreciated.

This is the post (and those linked within it) that I have used to get this far:
http://www.c2forum.com/viewtopic.php?f= ... rapper+dll

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Re: Vb.net dll problems

Post by haboustak » April 1st, 2015, 12:39 pm

To use more advanced PInvoke functionality you need to switch to using System.Runtime.InteropServices.DllImportAttribute. That's the only way to import non-VB-compatible DLLs into VB.NET projects (anything that's not StdCall).

For anyone that's using the DLLs in managed code the key things to know are:
1: The libraries all use cdecl calling convention.
2: The CSafe DLL is compiled using a C++ compiler and the exports are not extern "C". As a result, the entry point names are mangled and you need to specify the mangled name when importing. This only applies to the CSafe dll, the other two Dlls use C-style exports.

I'm not a VB.NET developer, but I wrote and tested the following code and it works for VS 2013 and my Dlls dated 3/26/2008. It should get you started (if you still want to try).

I wrote DllImport attribute declarations for all imported functions. I did not use Declare because it doesn't support CallingConvention. I set the EntryPoint field on the attribute when necessary using the entry point name found using Depends.exe against PMCSafeCP.dll.

Code: Select all

Imports System.Runtime.InteropServices

Public Class Form1
    <DllImport("PM3USBCP.dll", CallingConvention:=CallingConvention.Cdecl)> _
    Overloads Shared Function tkcmdsetUSB_init() As UShort
    End Function

    <DllImport("PM3DDICP.dll", CallingConvention:=CallingConvention.Cdecl)> _
    Overloads Shared Function tkcmdsetDDI_init() As UShort
    End Function

    <DllImport("PM3DDICP.dll", CallingConvention:=CallingConvention.Cdecl)> _
    Overloads Shared Function tkcmdsetDDI_discover_pm3s( _
        ProductName As String, StartAddress As UShort, ByRef NumUnits As UShort) As UShort
    End Function

    <DllImport("PM3CSafeCP.dll", CallingConvention:=CallingConvention.Cdecl, EntryPoint:="?tkcmdsetCSAFE_init_protocol@@YAFG@Z")> _
    Overloads Shared Function tkcmdsetCSAFE_init_protocol(Timeout As UShort) As UShort
    End Function

    <DllImport("PM3CSafeCP.dll", CallingConvention:=CallingConvention.Cdecl, EntryPoint:="?tkcmdsetCSAFE_command@@YAFGGQAKPAG0@Z")> _
    Overloads Shared Function tkcmdsetCSAFE_command( _
        Address As UShort, _
        CmdSize As UShort, _
        Command As Integer(), _
        ByRef RspSize As UShort, _
        Response As Integer() _
        ) As UShort
    End Function

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim ResponseCode
        Dim NumUnits = 0
        Dim Timeout = 1000
        Dim Cmd(0) As Integer, CmdSize As UShort, Rsp(63) As Integer, RspSize As UShort
        CmdSize = 1
        Cmd(0) = &HA0
        RspSize = 64

        ResponseCode = tkcmdsetUSB_init()
        ResponseCode = tkcmdsetDDI_init()
        ResponseCode = tkcmdsetCSAFE_init_protocol(TimeOut)
        ResponseCode = tkcmdsetDDI_discover_pm3s("Concept2 Performance Monitor", 0, NumUnits)
        ResponseCode = tkcmdsetCSAFE_command(0, CmdSize, Cmd, RspSize, Rsp)
    End Sub
End Class

Post Reply