Is it possible to have an array of types ?
-
For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false. At the moment I do something along the lines of:
typedef void (*p2DLLFunc1) (void);
typedef char* (*p2DLLFunc2) (void);bool CDLLWrapper::LoadDLL()
{
bool bResult = false;m\_hmoduleDll = ::LoadLibrary(\_T("DLLName")); if (NULL != m\_hmoduleDll) { // DLL loaded successfully. Now get addresses of all functions we are supporting m\_funcDLLFunc1 = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc1"))); m\_funcDLLFunc2 = reinterpret\_cast<p2DLLFunc2>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc2"))); m\_funcDLLFunc3 = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc3"))); if ( NULL != m\_funcDLLFunc1 && NULL != m\_funcDLLFunc2 && NULL != m\_funcDLLFunc3) { // SUCCESS: All wrapped functions found in DLL bResult = true; } else { // FAILURE: Could not find one or more wrapped functions ::FreeLibrary(m\_hmoduleDll); } } return bResult;
}
However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so
bool CDLLWrapper::LoadDLL()
{
struct MyLUT {
TCHAR* tcFuncName;
funcDLLFunc;
int iFunctionSignatureType;
}; // struct MyLUT {static MyLUT arrWrappedFuncs\[\] = { \_T("DLLFunc1"), m\_funcDLLFunc1, 0 \_T("DLLFunc2"), m\_funcDLLFunc2, 1 \_T("DLLFunc3"), m\_funcDLLFunc3, 0 }; // static MyLUT arrWrappedFuncs\[\] const int iNUM\_WRAPPED\_FUNCTIONS = sizeof(arrWrappedFuncs) / sizeof(MyLUT); bool bResult = false; m\_hmoduleDll = ::LoadLibrary(\_T("DLLName")); if (NULL != m\_hmoduleDll) { // DLL loaded successfully. Now get addresses of all functions we are supporting bResult = true; // Assume success for (int i = 0; i < iNUM\_WRAPPED\_FUNCTIONS; ++i) { switch(arrWrappedFuncs\[i\].iFunctionSignatureType) { case 0: { arrWrappedFuncs\[i\].funcDLLFunc = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, arrWrappedFuncs\[i\].tcFuncName)); } break; case 1: {
-
For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false. At the moment I do something along the lines of:
typedef void (*p2DLLFunc1) (void);
typedef char* (*p2DLLFunc2) (void);bool CDLLWrapper::LoadDLL()
{
bool bResult = false;m\_hmoduleDll = ::LoadLibrary(\_T("DLLName")); if (NULL != m\_hmoduleDll) { // DLL loaded successfully. Now get addresses of all functions we are supporting m\_funcDLLFunc1 = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc1"))); m\_funcDLLFunc2 = reinterpret\_cast<p2DLLFunc2>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc2"))); m\_funcDLLFunc3 = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc3"))); if ( NULL != m\_funcDLLFunc1 && NULL != m\_funcDLLFunc2 && NULL != m\_funcDLLFunc3) { // SUCCESS: All wrapped functions found in DLL bResult = true; } else { // FAILURE: Could not find one or more wrapped functions ::FreeLibrary(m\_hmoduleDll); } } return bResult;
}
However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so
bool CDLLWrapper::LoadDLL()
{
struct MyLUT {
TCHAR* tcFuncName;
funcDLLFunc;
int iFunctionSignatureType;
}; // struct MyLUT {static MyLUT arrWrappedFuncs\[\] = { \_T("DLLFunc1"), m\_funcDLLFunc1, 0 \_T("DLLFunc2"), m\_funcDLLFunc2, 1 \_T("DLLFunc3"), m\_funcDLLFunc3, 0 }; // static MyLUT arrWrappedFuncs\[\] const int iNUM\_WRAPPED\_FUNCTIONS = sizeof(arrWrappedFuncs) / sizeof(MyLUT); bool bResult = false; m\_hmoduleDll = ::LoadLibrary(\_T("DLLName")); if (NULL != m\_hmoduleDll) { // DLL loaded successfully. Now get addresses of all functions we are supporting bResult = true; // Assume success for (int i = 0; i < iNUM\_WRAPPED\_FUNCTIONS; ++i) { switch(arrWrappedFuncs\[i\].iFunctionSignatureType) { case 0: { arrWrappedFuncs\[i\].funcDLLFunc = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, arrWrappedFuncs\[i\].tcFuncName)); } break; case 1: {
Whz do you need reinterpret_cast at the first place? Shouldn't that work without any casting?
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
-
Whz do you need reinterpret_cast at the first place? Shouldn't that work without any casting?
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
Unfortunately not, as you get a compiler error: error C2440: '=' : cannot convert from 'FARPROC' to 'p2DLLFunc1'
-
Unfortunately not, as you get a compiler error: error C2440: '=' : cannot convert from 'FARPROC' to 'p2DLLFunc1'
Try something like:
struct MyLUT { TCHAR\* tcFuncName; FARPROC \*funcDLLFunc; }; // struct MyLUT {
static MyLUT arrWrappedFuncs[] = { {_T("DLLFunc1"), (FARPROC *)&m_funcDLLFunc1},
{_T("DLLFunc2"), (FARPROC *)&m_funcDLLFunc2},
{_T("DLLFunc3"), (FARPROC *)&m_funcDLLFunc3},
}; // static MyLUT arrWrappedFuncs[]
...
(*arrWrappedFuncs[i].funcDLLFunc) = GetProcAddress(m_hmoduleDll, arrWrappedFuncs[i].tcFuncName));
...I just modified your code, so it might not compile, and probably needs adjustment here and there but maybe you get the main idea.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
-
Try something like:
struct MyLUT { TCHAR\* tcFuncName; FARPROC \*funcDLLFunc; }; // struct MyLUT {
static MyLUT arrWrappedFuncs[] = { {_T("DLLFunc1"), (FARPROC *)&m_funcDLLFunc1},
{_T("DLLFunc2"), (FARPROC *)&m_funcDLLFunc2},
{_T("DLLFunc3"), (FARPROC *)&m_funcDLLFunc3},
}; // static MyLUT arrWrappedFuncs[]
...
(*arrWrappedFuncs[i].funcDLLFunc) = GetProcAddress(m_hmoduleDll, arrWrappedFuncs[i].tcFuncName));
...I just modified your code, so it might not compile, and probably needs adjustment here and there but maybe you get the main idea.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
FARPROC is defined as a function pointer to a function that receives no input, and returns an int (ie. int func(void)). Therefore, this cannot be used for functions whose parameter list and return type are different (eg. char* func1(int)).
-
FARPROC is defined as a function pointer to a function that receives no input, and returns an int (ie. int func(void)). Therefore, this cannot be used for functions whose parameter list and return type are different (eg. char* func1(int)).
A pointer in itself is just a memory address, what parameters how are passed upon a call is decided where and when you call the function thorough the pointer, but correct me if i am wrong. Just try this:
void *P1 = (void *)GetProcAddress(DLLHande, "proc_name");
FARPROC P2 = GetProcAddress(DLLHande, "proc_name");
pDLLFunc1 P3 = (pDLLFunc1)GetProcAddress(DLLHande, "proc_name");
pDLLFunc1 P4 = reinterpret_cast(GetProcAddress(DLLHande, "proc_name"));And check out the 4 pointer values (for example in the watch window of your debugger if you are using Visual Studio), they all should be the same,
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
-
A pointer in itself is just a memory address, what parameters how are passed upon a call is decided where and when you call the function thorough the pointer, but correct me if i am wrong. Just try this:
void *P1 = (void *)GetProcAddress(DLLHande, "proc_name");
FARPROC P2 = GetProcAddress(DLLHande, "proc_name");
pDLLFunc1 P3 = (pDLLFunc1)GetProcAddress(DLLHande, "proc_name");
pDLLFunc1 P4 = reinterpret_cast(GetProcAddress(DLLHande, "proc_name"));And check out the 4 pointer values (for example in the watch window of your debugger if you are using Visual Studio), they all should be the same,
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
You are correct, and that is the problem. If I don't cast it to the correct type when calling GetProcAddress(), I will have to cast it later on when I call the function pointed to by the pointer. Either way, I will need to cast it at some point. Otherwise I don't think it will let me call it with the relevant parameters and return type. I will have to do some testing to be sure, but my current understanding makes me think it won't work.
-
You are correct, and that is the problem. If I don't cast it to the correct type when calling GetProcAddress(), I will have to cast it later on when I call the function pointed to by the pointer. Either way, I will need to cast it at some point. Otherwise I don't think it will let me call it with the relevant parameters and return type. I will have to do some testing to be sure, but my current understanding makes me think it won't work.
How about a different aproach, use a template class, something like this:
class CConverterBase
{
public:
virtual operator void =(const FARPROC ptr) = 0;
};template
class CConverter: public CConverterBase
{
TFuncPtr &fFuncPtrPtr;
public:
CConverter(TFuncPtr &ptr):fFuncPtrPtr(ptr) {}operator void =(const FARPROC ptr)
{
fFuncPtrPtr = (TFuncPtr)ptr;
return fFuncPtrPtr;
}
}And then something like:
class Func
{
TCHAR *pszName;
CConverterBase *ptr;
};
...
Func FuncArr[] = {{_T"DLLFunc1", new CConverter(m_DLLFunc1)}, {_T"DLLFunc2", new CConverter(m_DLLFunc2)}, ...};
...
(*FuncAtt[I].ptr) = GetProcAddress(dllhandle, FuncAtt[I].pszName);
...And of course don't forget to free up the objects you instantiated.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
-
How about a different aproach, use a template class, something like this:
class CConverterBase
{
public:
virtual operator void =(const FARPROC ptr) = 0;
};template
class CConverter: public CConverterBase
{
TFuncPtr &fFuncPtrPtr;
public:
CConverter(TFuncPtr &ptr):fFuncPtrPtr(ptr) {}operator void =(const FARPROC ptr)
{
fFuncPtrPtr = (TFuncPtr)ptr;
return fFuncPtrPtr;
}
}And then something like:
class Func
{
TCHAR *pszName;
CConverterBase *ptr;
};
...
Func FuncArr[] = {{_T"DLLFunc1", new CConverter(m_DLLFunc1)}, {_T"DLLFunc2", new CConverter(m_DLLFunc2)}, ...};
...
(*FuncAtt[I].ptr) = GetProcAddress(dllhandle, FuncAtt[I].pszName);
...And of course don't forget to free up the objects you instantiated.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
I've been thinking a similar thing that I might have to use some C++ features to achieve what I'm after. The idea of a template class is good, but the FuncArr[] can only be initialized with static data (ie. known at compile time). Hmmm, time to put my C++ hat on :)
-
For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false. At the moment I do something along the lines of:
typedef void (*p2DLLFunc1) (void);
typedef char* (*p2DLLFunc2) (void);bool CDLLWrapper::LoadDLL()
{
bool bResult = false;m\_hmoduleDll = ::LoadLibrary(\_T("DLLName")); if (NULL != m\_hmoduleDll) { // DLL loaded successfully. Now get addresses of all functions we are supporting m\_funcDLLFunc1 = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc1"))); m\_funcDLLFunc2 = reinterpret\_cast<p2DLLFunc2>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc2"))); m\_funcDLLFunc3 = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc3"))); if ( NULL != m\_funcDLLFunc1 && NULL != m\_funcDLLFunc2 && NULL != m\_funcDLLFunc3) { // SUCCESS: All wrapped functions found in DLL bResult = true; } else { // FAILURE: Could not find one or more wrapped functions ::FreeLibrary(m\_hmoduleDll); } } return bResult;
}
However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so
bool CDLLWrapper::LoadDLL()
{
struct MyLUT {
TCHAR* tcFuncName;
funcDLLFunc;
int iFunctionSignatureType;
}; // struct MyLUT {static MyLUT arrWrappedFuncs\[\] = { \_T("DLLFunc1"), m\_funcDLLFunc1, 0 \_T("DLLFunc2"), m\_funcDLLFunc2, 1 \_T("DLLFunc3"), m\_funcDLLFunc3, 0 }; // static MyLUT arrWrappedFuncs\[\] const int iNUM\_WRAPPED\_FUNCTIONS = sizeof(arrWrappedFuncs) / sizeof(MyLUT); bool bResult = false; m\_hmoduleDll = ::LoadLibrary(\_T("DLLName")); if (NULL != m\_hmoduleDll) { // DLL loaded successfully. Now get addresses of all functions we are supporting bResult = true; // Assume success for (int i = 0; i < iNUM\_WRAPPED\_FUNCTIONS; ++i) { switch(arrWrappedFuncs\[i\].iFunctionSignatureType) { case 0: { arrWrappedFuncs\[i\].funcDLLFunc = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, arrWrappedFuncs\[i\].tcFuncName)); } break; case 1: {
Defenestration wrote:
Any ideas ?
Have you read this article on dynamic linking?
"Love people and use things, not love things and use people." - Unknown
"The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch
-
For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false. At the moment I do something along the lines of:
typedef void (*p2DLLFunc1) (void);
typedef char* (*p2DLLFunc2) (void);bool CDLLWrapper::LoadDLL()
{
bool bResult = false;m\_hmoduleDll = ::LoadLibrary(\_T("DLLName")); if (NULL != m\_hmoduleDll) { // DLL loaded successfully. Now get addresses of all functions we are supporting m\_funcDLLFunc1 = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc1"))); m\_funcDLLFunc2 = reinterpret\_cast<p2DLLFunc2>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc2"))); m\_funcDLLFunc3 = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc3"))); if ( NULL != m\_funcDLLFunc1 && NULL != m\_funcDLLFunc2 && NULL != m\_funcDLLFunc3) { // SUCCESS: All wrapped functions found in DLL bResult = true; } else { // FAILURE: Could not find one or more wrapped functions ::FreeLibrary(m\_hmoduleDll); } } return bResult;
}
However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so
bool CDLLWrapper::LoadDLL()
{
struct MyLUT {
TCHAR* tcFuncName;
funcDLLFunc;
int iFunctionSignatureType;
}; // struct MyLUT {static MyLUT arrWrappedFuncs\[\] = { \_T("DLLFunc1"), m\_funcDLLFunc1, 0 \_T("DLLFunc2"), m\_funcDLLFunc2, 1 \_T("DLLFunc3"), m\_funcDLLFunc3, 0 }; // static MyLUT arrWrappedFuncs\[\] const int iNUM\_WRAPPED\_FUNCTIONS = sizeof(arrWrappedFuncs) / sizeof(MyLUT); bool bResult = false; m\_hmoduleDll = ::LoadLibrary(\_T("DLLName")); if (NULL != m\_hmoduleDll) { // DLL loaded successfully. Now get addresses of all functions we are supporting bResult = true; // Assume success for (int i = 0; i < iNUM\_WRAPPED\_FUNCTIONS; ++i) { switch(arrWrappedFuncs\[i\].iFunctionSignatureType) { case 0: { arrWrappedFuncs\[i\].funcDLLFunc = reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, arrWrappedFuncs\[i\].tcFuncName)); } break; case 1: {
You can use a MS extension in
GetProcAddress()
calls:(FARPROC&) func_ptr = GetProcAddress ( hModule, "FunctionName" );
That way you don't have to make a new typedef for each function pointer.
--Mike-- Visual C++ MVP :cool: LINKS~! CP SearchBar v3.0 | C++ Forum FAQ "That's what's great about doing user interface work. No matter what you do, people will say that what you did was idiotic." -- Raymond Chen