0

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

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

从 C++ 调用 dll 函数

并尝试通过我在这里找到的代码使用 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。

4

2 回答 2

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可能也需要以相同的方式进行更改,但也许不需要。

于 2013-07-02T18:26:28.623 回答
1

这里有几点。LoadLibrary 的签名:

HMODULE WINAPI LoadLibrary(_In_  LPCTSTR lpFileName);

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

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

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

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

于 2013-07-02T18:28:59.780 回答