I have a simple question which is breaking my mind.
On my solution, I'm working with a DLL that offers me the following function:
int RegisterCallback(TCallbackType CallbackType, void *pLLTProfileCallback, void *pUserData);
For more information, the parameter pLLTProfileCallback is a function type defined as:
typedef void (__stdcall *TNewProfile_s)(const unsigned char *pData,
unsigned int nSize, void *pUserData);
I'm trying to insert my function 'NewProfile' in this parameter as follows:
RegisterCallback(STD_CALL, (void*)NewProfile, m_pLLT1);
But it says: 'Error: invalid type conversion'.
The function definition for 'NewProfile' is:
void __stdcall NewProfile(const unsigned char* pucData, unsigned int uiSize, void* pUserData){...}
Where is my error exactly? What can I do in order to fix it?
Related
Using Visual Studio 2017, I have a section of code where I define a std::map that compiles fine in x64 but returns an error when compiled for x86.
The map in question keys on an enum and returns a struct with a descriptor string and some function pointers.
I went through my project settings and confirmed the only difference in my C++ compiler settings between the two is the architecture flag. My best guess is it has something to do with the function pointers in each map entry, since I have other std::maps in this same file containing structs of strings and doubles/floats that all work fine.
The specific error thrown is C2440: Can't convert from type1 to type2, with the text cannot convert from 'initializer list' to std::map<int,PropertyMetaData, std::less<_Kty>, std::allocator<std::pair<const _Kty,_Ty>>>
EDIT:
I made the most compact example I could without any external dependencies. I get no errors in x64 but I get the type conversion error when set to x86:
#include <map>
typedef double(*convertFunc)(int, int, double);
typedef int(*convertFuncD)(int, int, double*,double*,int);
extern "C" {
__declspec(dllexport) double __stdcall Pressure(
int inUnits,
int outUnits,
double inValue
);
__declspec(dllexport) int __stdcall PressureD(
int inUnits,
int outUnits,
double* inValue,
double* outValue,
int n
);
}
//Metadata for each Property
struct PropertyMetaData {
const char desc[20]; //Text description
const convertFunc func; //double conversion function
const convertFuncD funcArrayD; //array double conversion function
};
// Map containing all of the properties and their metadata
typedef std::map<int, PropertyMetaData> PropertiesMap;
const PropertiesMap conversions = {
//Mapping The type of unit (mass, distance, etc.) to the appropriate function
//Enumeration {desc[20], func, arrayfuncD, arrayFuncF }
{ 1, {"Pressure", Pressure, PressureD}},
};
After some more experimenting, it seems to be caused by the __stdcall qualifier. If that's removed, I have no issues with either architecture.
Got it! The problem was the inclusion of __stdcall in the function declaration, or rather the omission of __stdcall in the function pointer type definition. It seems like with certain combinations of architecture, the __stdcall may or may not cause a type conversion error if __stdcall is not also in the pointer type definition. Declaring my function pointer type as follows:
typedef double(__stdcall *convertFunc)(EUnits, EUnits, double);
typedef int(__stdcall *convertFuncD)(EUnits, EUnits, double*,double*,int);
typedef int(__stdcall *convertFuncF)(EUnits, EUnits, float*, float*, int);
resolved the error!
First and foremost, I'm a C# developer working on a project that was thrust on me and I'm feeling very outside of my comfort zone.
That being said, I'm currently attempting to pass 2 callback functions to a C library. I have the functions defined as free functions in my C++ console application.
When I run the application I'm receiving the following extremely unhelpful error at the point that I attempt to pass the functions to the library.
Exception thrown at 0x0000000000000000 in YourApp.exe: 0xC0000005: Access violation executing location 0x0000000000000000
The callbacks are defined in the header file for the accompanying C source file which I have listed below. Note, I did not write the following header.
header.h
typedef void( __stdcall * Callback1 )( void *, int, unsigned int, int, int, int, int );
typedef void( __stdcall * Callback2 )( void *, int, int, unsigned int, unsigned int );
__declspec(dllimport) int open( Callback1 cb1, Callback2 cb2 );
From my C++ console application I first include the C header.
extern "C"
{
#include "header.h"
}
I then declare the 2 free functions I'm attempting to pass as parameters to the open function exposed through the header.h file.
void __stdcall callback1(
void *data,
int count,
unsigned int colorId,
int flag,
int pageNumber,
int width,
int height )
{
if ( count <= 0 ) return;
std::cout << "callback1" << std::endl;
}
void __stdcall callback2(
void *data,
int count,
int offset,
unsigned int colorId,
unsigned int side )
{
if ( count <= 0 ) return;
std::cout << "callback2" << std::endl;
}
Within main I then attempt to pass the above functions as parameters to the open function.
int main( int argc, char *argv[ ], char *envp[ ] )
{
// This is the line where the error is thrown.
open( callback1, callback2 );
}
I'm currently using VS2015. I'm unsure how to proceed as I find that error extremely unhelpful.
I'm currently doing everything in the code file that main is defined in. So the functions I have posted above are not methods of a class.
I have successfully integrated openssl dev library in main.cpp file. openssl/evp.h is currently included.
I can use EVP_DigestInit, EVP_DigestUpdate functions successfully without any error. But if I try to call EVP_DigestFinal, it gives following error:
No matching function for call to 'EVP_DigestFinal'
Whereas, the functions are defined in the same header file, evp.h. What should I do in order to use this function too? Thanks for help.
Related code:
EVP_MD_CTX ctx;
char ch[128];
int val = 128;
EVP_DigestFinal(&ctx, ch, val);
From what I find at OpenSSL.org, the signature is
int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, int *s);
To match that you need unsigned char for the second parameter and an address for the third parameter, something like
EVP_MD_CTX ctx;
unsigned char ch[128];
_______^
int val = 128;
EVP_DigestFinal(&ctx, ch, &val);
__________________________^
In some SDK I have a method which takes function pointer.
int AutoRead(nAutoRead aEventFun)
where parameter is:
typedef int (__stdcall *nAutoRead)(char *data);
Now I want to use this function in my code like this:
// First need to get pointer to actual function from DLL
CV_AutoRead AutoRead; // CV_AutoRead is typedef for using function pointer
AutoRead = (CV_AutoRead)GetProcAddress(g_hdll,"AutoRead");
// Now I want to use the SDK method and set callback function,
// but I get error on the next line
// error is: 'initializing' : cannot convert from 'int (__cdecl *)(char *)' to 'TOnAutoRead'
nAutoRead f = &callbackFunc;
if(0 == AutoRead(f)) // AutoRead - now refers to the SDK function shown initially
{
}
where callbackFunc is:
int callbackFunc(char *data)
{
}
Apparently I am doing something wrong. But what?
ps. This is typedef for CV_AutoRead
typedef int (CALLBACK* CV_AutoRead)(nAutoRead aEventFun);
This has to do with the calling convention specifier __stdcall that the callback requires. By default your callbackFunc uses __cdecl, causing an error.
To fix this problem, declare callbackFunc as follows:
int __stdcall callbackFunc(char *);
You also need to add __stdcall to the function definition.
See Argument Passing and Naming Conventions for more information on this subject.
Trying to get a clean compile here, but I get this:
recorders/r5000/r5k_sat.c:179:6: warning: no previous prototype for ‘sat_find_chname’ [-Wmissing-prototypes]
void sat_find_chname(unsigned char *buf, struct sids *sids, unsigned int size) {
When I put in r5000_internal.h (the header file for r5k_sat.c):
void sat_find_chname(unsigned char *buf, struct sids *sids, unsigned int size)
... I get: https://pastee.org/3u3dh
(forum won't allow me to post it here)