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.
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.
Access violation reading location 0x00000051.
This tells me the function is treating PCAN_USBBUS1 as a pointer. Perhaps:
#define PCAN_USBBUS1 0x51
should be changed to
WORD pcan_usbbus1 = 0x51;
And the call to CAN_Init should be changed to:
int intMyReturnVal = CAN_Init(&pcan_usbbus1, CAN_BAUD_1M);
The function signature should probably be something like:
typedef int (__stdcall * pICFUNC)(WORD* wBTR0BTR1, int CANMsgType);
^ pointer here
I imagine CAN_BAUD_1M might also need to be changed in the same way but maybe not.
Related
I have a class in the main module that holds a list of stuff. I'd like to add some stuff to that list in a dll. Items in the list could be added and removed (allocated/deallocated) arbitrarily.
My understanding is that it's bad form to delete data allocated in one module from another. Can I somehow allocate data using the main module heap from a dll? If not, is there a safe way to delete data allocated in a dll from the main module?
Ideally, a solution would work on both Linux and Windows. Here's an example (that works) in Windows.
Notice that in Main.cpp I'm deleting an allocation made in the DynamicModule dll and Windows doesn't throw any exceptions. I was expecting one, thinking that the main module shouldn't be able to delete an allocation made on the dll's heap.
// Main.cpp
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
#include "LibClass.h"
typedef void (*DLLFunc)(LibClass*);
DLLFunc dllFunc;
HMODULE LoadDynamicLib()
{
std::string libPath("Release/DynamicModule.dll");
const size_t cSize = strlen(libPath.c_str()) + 1;
wchar_t* wc = new wchar_t[cSize];
size_t outSize;
mbstowcs_s(&outSize, wc, cSize, libPath.c_str(), cSize - 1);
HMODULE handle = LoadLibrary(wc);
assert(handle != 0);
delete[] wc;
dllFunc = reinterpret_cast<DLLFunc>(GetProcAddress(handle, "AddNames"));
return handle;
}
int main(int argc, char** argv)
{
HMODULE handle = LoadDynamicLib();
LibClass lib;
float *firstVal = new float(1.0f);
lib.values.push_back(firstVal);
if (handle) dllFunc(&lib);
delete lib.values[1];
lib.values.pop_back();
lib.values.clear(); // does this dealloc items or just removes them??
FreeLibrary(handle);
return 0;
}
// LibClass.h
#pragma once
#include <vector>
#ifdef _WINDLL
#define LIBAPI __declspec(dllexport)
#else
#define LIBAPI __declspec(dllimport)
#endif
struct LibClass {
std::vector<float*> values;
};
// DynamicModule.cpp
#include "../testcppdll/LibClass.h"
extern "C"
{
LIBAPI void AddNames(LibClass *_libClass) {
if (_libClass) {
float* newStr = new float(3.0f);
_libClass->values.push_back(newStr);
}
}
}
I'm calling a function in an undocumented DLL which unpacks a file.
There must be a mistake in the way the header is declared / allocated but can't figure out what is going wrong.
Project character set in VS 2010 is Unicode.
Can call the DLL function succesfully from C# with the snippet below (but I need to make it work in c++):
[DllImport("unpacker.dll", EntryPoint = "UnpackFile", PreserveSig = false)]
internal static extern IntPtr UnpackFile(byte[] file, int fileSize,
[MarshalAs(UnmanagedType.LPWStr)] StringBuilder header, int headerSize);
If I uncomment of move one the headers an Acccess Violation pops up. The function also returns 0 which it doesn't in C#.
Any thoughts?
Code in the VC++ 2010 project:
// unpacker.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <fstream>
using namespace std;
typedef void* (*UnpackFile)(unsigned char*, int, LPTSTR, int);
int _tmain(int argc, _TCHAR* argv[])
{
LPTSTR header;
//Move this and get a access violation on the _UnpackFile(filetounpack... line
static unsigned char *filetounpack; //Buffer to byte array with the file to unpack
int filelen; //variable to store the length of the file
HINSTANCE dllHandle; // Handle to DLL
UnpackFile _UnpackFile; // Function pointer
ifstream filetoread; //Stream class to read from files
static LPTSTR header2; //Buffer for the header 2nd
filetoread.open ("c:/projects/testfile.bin", ios::in | ios::binary|ios::ate);
filelen = filetoread.tellg(); //read the length
filetounpack = new unsigned char [filelen]; //allocate space
filetoread.seekg (0, ios::beg); //set beginning
filetoread.read ((char *)filetounpack, filelen); //read the file into the buffer
filetoread.close(); //close the file
dllHandle = LoadLibrary(_T("unpacker.dll"));
_UnpackFile = (UnpackFile)GetProcAddress(dllHandle, "UnpackFile");
//header = new _TCHAR[filelen]; //Allocate memory for header
header2 = new _TCHAR[filelen]; //Allocate memory for header
//Access violation reading location 0xffffffffffffffff!!!
void* tmp = _UnpackFile(filetounpack ,filelen ,header2 ,filelen);
delete[] filetounpack;
delete[] header;
delete[] header2;
FreeLibrary(dllHandle);
return 0;
}
typedef void* (*UnpackFile)(unsigned char*, int, LPTSTR, int);
That does not match the CallingConvention property of your C# declaration. The default for C# is StdCall, the default for native C++ projects is __cdecl. Fix:
typedef void* (__stdcall * UnpackFile)(unsigned char*, int, LPTSTR, int);
And keep in mind that error checking is never optional in C++, you really do need to check if LoadLibrary() and GetProcAddress() succeeded. Automatic in C#, not in C++. Both functions return NULL when they fail.
I have an existing file on the computer and I was wondering if it is possible to know when it was made, Size of the file, and more properties on the file..
I tried to use in ifstream But there's the information I have on file
(I'm using Visual C++ 6.0,Cannot using Boost)
Look at function GetFileAttributesEx.
#include <windows.h>
WIN32_FILE_ATTRIBUTE_DATA fInfo;
GetFileAttributesEx("test.dat", GetFileExInfoStandard, &fInfo);
The WIN32_FILE_ATTRIBUTE_DATA contains a lot of the "common" file informations (size, creation/edit time, attributes).
Update: I just saw, that you're using Visual C++ 6. Since GetFileAttributesEx is supported since Windows XP it might not be available in your WIN API headers... You can use the function by dynamic linking. The following code does the same thing as the snippet from above:
/* clone definition of WIN32_FILE_ATTRIBUTE_DATA from WINAPI header */
typedef struct file_info_struct
{
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
} FILE_INFO;
/* function pointer to GetFileAttributesEx */
typedef BOOL (WINAPI *GET_FILE_ATTRIBUTES_EX)(LPCWSTR lpFileName, int fInfoLevelId, LPVOID lpFileInformation);
HMODULE hLib;
GET_FILE_ATTRIBUTES_EX func;
FILE_INFO fInfo;
hLib = LoadLibrary("Kernel32.dll");
if (hLib != NULL)
{
func = (GET_FILE_ATTRIBUTES_EX)GetProcAddress(hLib, "GetFileAttributesExW");
if (func != NULL)
{
func("test.dat", 0, &fInfo);
}
FreeLibrary(hLib);
/*
** Don't call func after FreeLibrary !!!
** It should be ok since kernel32.dll is loaded by your application anyway but if
** you get a function pointer from a dll only loaded by LoadLibrary the function
** pointer is invalid once the library if freed.
*/
}
The size and creation data (and more) are available via FindFirstFile.
I want to use pjsipDll.dll in a c++ code. I got this dll from one of the sites, I only know how to build the code to obtain the dll file. So I did that and now I've the pjsipDll.dll file with me. I want to use certain functions in the DLL in my code(C++)
I tried the following code. << I haven't made/added any dll or .h file to the project, there is only the following CPP file>>
#include <iostream>
using namespace std;
int CallMyDLL(void)
{
/* get handle to dll */
HINSTANCE hGetProcIDDLL = LoadLibrary("G:\\July\\9.0\\pjsipdll\\Lib\\pjsipDll.dll");
/* get pointer to the function in the dll*/
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"dll_makeCall");
/*
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)(int, char *);
pICFUNC MyFunction;
MyFunction = pICFUNC(lpfnGetProcessID);
/* The actual call to the function contained in the dll */
int intMyReturnVal = MyFunction(5,"hello");
/* Release the Dll */
FreeLibrary(hGetProcIDDLL);
/* The return val from the dll */
returnintMyReturnVal;
}
void main()
{
cout<<"Hello World";
CallMyDLL();
getchar();
}
I learnt this way from some site, to use the function from a DLL.
The problem is, I get an ERROR:
error C2065: 'HINSTANCE' : undeclared identifier g:\july\9.0\pjproject-0.9.0\myproject\importerprojet\importerprojet\mycpp.cpp 9 importerProjet
Can anyone help me out with this. Or atleast point me to the post if this query is already addressed.
Thanks for your help,
Vinu.
You need to #include <windows.h>
I have been reading one of the Hoglund titles and I though, reading great, but can I make it work? Why do they provide non-working examples in books?
#include "stdafx.h"
#include <cstdio>
#include <windows.h>
#include <winbase.h>
#include <tlhelp32.h>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hProcess;
DEBUG_EVENT dbg_evt;
int aPID;
if(argc != 2)
{
printf("wrong number of params\nusage %s<pid>\n", argv[0]);
return 0;
}
//load the ptr to fDebugSetProcessKillOnExit
fDebugSetProcessKillOnExit = (DEBUGSETPROCESSKILLONEXIT)
GetProcAddress(GetModuleHandle("kernel32.dll"),
"DebugSetProcessKillOnExit");
if(!fDebugSetProcessKillOnExit)
{
printf("[!] failed to get fDebugSetProcessKillOnExit function!\n");
}
aPID = atoi(argv[1]);
}
I am getting two error messages:
fDebugSetProcessKillOnExit is an undeclared identifier
What type should it be?
"Error 4 error C2664: 'GetModuleHandleW' : cannot convert parameter 1 from 'const char [13]' to 'LPCWSTR'
What type should the fDebug... be? Why doesn't the aPid = atoi... line work?
Should the project be compiled in C instead of C++, as this is exactly as it is in the book?
Thanks, R.
Taking this from MSDN:
BOOL WINAPI DebugSetProcessKillOnExit(__in BOOL KillOnExit);
you can declare the function pointer as:
BOOL (*fDebugSetProcessKillOnExit)(BOOL) = /* ... */;
or ease your eyes by using typedef:
typedef BOOL (*DebugKillPtr)(BOOL);
DebugKillPtr fDebugSetProcessKillOnExit = /* ... */;
Function pointers can be somewhat confusing, InformITs guide on them should help with that.
Additionally, you are using a Unicode build. You can either use GetModuleHandle(L"Kernel32.dll") or _T() etc. or set your project to use the multi-byte-character-set (project properties -> configuration -> general -> character set).
The unicode-character-set is also the reason why the atoi() statement can't work:
argv is an array of _TCHAR*s, and _TCHAR is wchar_t for unicode-builds. atoi() however expects a const char* argument and you are handing it a wchar_t*.
So you can either again use a multi-byte-character set, convert the string or use Microsofts _wtoi()/_ttoi().
To ease switching between character sets and stick with the style of the book, prefer the _T* and _t* versions.
The declaration for fDebugSetProcessKillOnExit is missing; probably it should be something like
DEBUGSETPROCESSKILLONEXIT fDebugSetProcessKillOnExit;
where DEBUGSETPROCESSKILLONEXIT should be a typedef to the prototype of that function.
You are compiling in Unicode and the book "thinks" that you're compiling in ANSI; you should change the strings passed to the APIs to generic strings with the _T() macro.
So, to sum everything up, you should simply change one line and add the typedef:
typedef BOOL (*DEBUGSETPROCESSKILLONEXIT)(BOOL);
//load the ptr to fDebugSetProcessKillOnExit
DEBUGSETPROCESSKILLONEXIT fDebugSetProcessKillOnExit = (DEBUGSETPROCESSKILLONEXIT) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), _T("DebugSetProcessKillOnExit"));