我目前正在尝试使用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。
答案 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时会发生这种情况!)。