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 に答える