How to access a function inside a dll file in C++

0

I am currently trying to communicate with a device using CAN. To do so I am using PCAN Basic using C++.

Unfortunately, I know nothing about accessing a function inside a dll file (which is what is provided). I found this link:

Calling a dll function from C++

and am trying to use LoadLibrary via code I found here:

http://www.goffconcepts.com/techarticles/development/cpp/calldll.html

My Code:

// dll_get_func.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <stdio.h> 
#include <conio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h> /* For sqrt() */
#include <windows.h> 

#define DELCLDIR __declspec("Pcan_usb.dll")
#define PCAN_USBBUS1 0x51
#define CAN_BAUD_1M     0x0014  //   1 MBit/s
#define MSGTYPE_STANDARD 0x00 

typedef struct {
    DWORD ID;        // 11/29 bit identifier
    BYTE  MSGTYPE;   // Bits from MSGTYPE_*
    BYTE  LEN;       // Data Length Code of the Msg (0..8)
    BYTE  DATA[8];   // Data 0 .. 7
} TPCANMsg;


int hardCodeInit(void)
{
    /* get handle to dll */
   HINSTANCE hGetProcIDDLL = LoadLibrary(_T("Pcan_usb.dll"));

   /* get pointer to the function in the dll*/
   FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"CAN_Init");

   /*
      Define the Function in the DLL for reuse. This is just prototyping the dll's function.
      A mock of it. Use "stdcall" for maximum compatibility.
   */
   typedef int (__stdcall * pICFUNC)(WORD wBTR0BTR1, int CANMsgType);

   pICFUNC CAN_Init;
   CAN_Init = pICFUNC(lpfnGetProcessID);
   //DWORD __stdcall CAN_Init(WORD wBTR0BTR1, int CANMsgType);  

   /* The actual call to the function contained in the dll */
   int intMyReturnVal = CAN_Init(PCAN_USBBUS1,CAN_BAUD_1M);

   /* Release the Dll */
   FreeLibrary(hGetProcIDDLL);

   /* The return val from the dll */
    return intMyReturnVal;
}
int hardCodeWrite(void)
{
   HINSTANCE hGetProcIDDLL = LoadLibrary(_T("Pcan_usb.dll"));
   FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"CAN_Write");
   typedef int (__stdcall * pICFUNC)(WORD wBTR0BTR1, TPCANMsg CANMsgType);
   pICFUNC CAN_Write;
   CAN_Write = pICFUNC(lpfnGetProcessID);

   TPCANMsg msgOut; 
   msgOut.MSGTYPE = MSGTYPE_STANDARD;
   msgOut.LEN = 1;
   msgOut.DATA[0] = 0x03; // 0x03 = Get ID

   int toReturn;
   toReturn = CAN_Write(PCAN_USBBUS1,msgOut);
   FreeLibrary(hGetProcIDDLL);
   return toReturn;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int derp=hardCodeInit();
    int herp=hardCodeWrite();
    std::cout<<derp;
    std::cout<<herp;
    _getch();
    return 0;
}

However, Visual Studio says that there is a:

Unhandled exception at 0x10001D95 (Pcan_usb.dll) in dll_get_func.exe: 0xC0000005: 
Access violation reading location 0x00000051.

I have Pcan_usb.dll and Pcan_usb.lib in the same folder and I am using visual studio 2012.

c++
dll
unhandled-exception
loadlibrary
can-bus
asked on Stack Overflow Jul 2, 2013 by code11 • edited May 23, 2017 by Community

2 Answers

1
Access violation reading location 0x00000051.

This tells me the function is treating PCAN_USBBUS1 as a pointer. Perhaps:

#define PCAN_USBBUS1 0x51

should be changed to

WORD pcan_usbbus1 = 0x51;

And the call to CAN_Init should be changed to:

int intMyReturnVal = CAN_Init(&pcan_usbbus1, CAN_BAUD_1M);

The function signature should probably be something like:

typedef int (__stdcall * pICFUNC)(WORD* wBTR0BTR1, int CANMsgType);
                                      ^ pointer here

I imagine CAN_BAUD_1M might also need to be changed in the same way but maybe not.

answered on Stack Overflow Jul 2, 2013 by Dave Rager
1

There are several points here. Signature of the LoadLibrary:

HMODULE WINAPI LoadLibrary(_In_  LPCTSTR lpFileName);

Remove unneeded casts. This will simplify reading and understanding your code.

FARPROC lpfnGetProcessID - the name of the variable is confusing. This might be a source of confusion or misunderstanding.

Regarding the AV - the signature of the CAN_Init function as you are trying to use it is wrong. From your post it is hard to tell for sure what is should be. Look into manual (if possible), header file, etc.

Main point - you should not release the library. There are rare cases when this is needed. Most likely your case does not need this. It is very difficult to believe that you need to reload the library (and this what happens when you call FreeLibrary/LoadLibrary!) between initing it and writing.

answered on Stack Overflow Jul 2, 2013 by Kirill Kobelev • edited Jul 2, 2013 by Kirill Kobelev

User contributions licensed under CC BY-SA 3.0