如何在C ++中访问dll文件中的函数

时间:2013-07-02 18:11:30

标签: c++ dll unhandled-exception loadlibrary can-bus

我目前正在尝试使用CAN与设备通信。为此,我使用C ++使用PCAN Basic。

不幸的是,我对访问dll文件中的函数一无所知(这是提供的)。我找到了这个链接:

Calling a dll function from C++

我正在尝试通过我在此处找到的代码使用LoadLibrary:

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

我的代码:

// 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;
}

然而,Visual Studio说有一个:

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

我在同一文件夹中有Pcan_usb.dll和Pcan_usb.lib,我正在使用visual studio 2012。

2 个答案:

答案 0 :(得分:1)

Access violation reading location 0x00000051.

这告诉我该函数将PCAN_USBBUS1视为指针。也许:

#define PCAN_USBBUS1 0x51

应改为

WORD pcan_usbbus1 = 0x51;

CAN_Init的调用应更改为:

int intMyReturnVal = CAN_Init(&pcan_usbbus1, CAN_BAUD_1M);

函数签名应该类似于:

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

我想CAN_BAUD_1M也可能需要以相同的方式进行更改,但可能不会。

答案 1 :(得分:1)

这里有几点。 LoadLibrary的签名:

HMODULE WINAPI LoadLibrary(_In_  LPCTSTR lpFileName);

删除不需要的演员表。这将简化阅读和理解您的代码。

FARPROC lpfnGetProcessID - 变量的名称令人困惑。这可能是混淆或误解的根源。

关于AV - 当您尝试使用它时,CAN_Init功能的签名是错误的。从你的帖子中很难确定应该是什么。查看手册(如果可能),头文件等。

要点 - 您不应该释放库。在极少数情况下需要这样做。很可能你的情况不需要这个。很难相信你需要在启动它和写入之间重新加载库(以及当你调用FreeLibrary / LoadLibrary时会发生这种情况!)。