code11 code11 - 3 months ago 9
C++ Question

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

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.

Answer

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.

Comments