Prev: Dialog Editor display slightly different than app's
Next: Video Card Performance Characteristics Effecting Text Glyph Rendering?
From: dushkin on 17 Jan 2010 10:20 Hi, I am having difficulties to load some procedures from a certain DLL. While I am able to load couple of them, I fail on some others. For example, I succeed to load lr_message procedure: ---------------------------------------------------------- From the DLL h file: #if defined(cplusplus) || defined(__cplusplus) extern "C" { #define PROTO(x) x #endif #ifdef _WIN32 /* LR_FUNC is used for the call-back functions of the compiled Vuser */ #define LR_FUNC CALLBACK /* LR_MSG_FUNC is used for the message functions */ #define LR_MSG_FUNC WINAPIV #else #define LR_FUNC __export WINAPI #define LR_MSG_FUNC FAR CDECL __export #endif int LR_MSG_FUNC lr_message PROTO((LPCSTR fmt, ...)); } ---------------------------------------------------------- In my h file: typedef int (*LR_MESSAGE)(LPCSTR fmt, ...); LR_MESSAGE pLrMessage; ---------------------------------------------------------- In my cpp file: pLrMessage = 0; pLrMessage = (LR_MESSAGE)GetProcAddress(m_hIrun, "lr_message"); if (pLrMessage == 0) AfxMessageBox("pLrMessage error!"); ---------------------------------------------------------- And it is fine. But, for other functions, on the same DLL I fail. For example: ---------------------------------------------------------- From the DLL h file: int WINAPI lr_save_string PROTO((const char * param_val, const char * param_name)); ---------------------------------------------------------- In my h file: typedef int (*LR_SAVE_STRING)(const char *param_value, const char *param_name); LR_SAVE_STRING pLrSaveStr; ---------------------------------------------------------- In my cpp file: pLrSaveStr = 0; pLrSaveStr = (LR_SAVE_STRING)GetProcAddress(m_hIrun, "lr_save_string"); if (pLrSaveStr == 0) AfxMessageBox("pLrSaveStr error!"); ---------------------------------------------------------- And I get the message box. Why? Thanks!
From: Giovanni Dicanio on 17 Jan 2010 10:46 "dushkin" <taltene(a)gmail.com> ha scritto nel messaggio news:996d7b1c-7d23-4a09-905e-9a43f215563d(a)e16g2000yqc.googlegroups.com... > I am having difficulties to load some procedures from a certain DLL. > While I am able to load couple of them, I fail on some others. > In my cpp file: > > pLrSaveStr = 0; > pLrSaveStr = (LR_SAVE_STRING)GetProcAddress(m_hIrun, > "lr_save_string"); > if (pLrSaveStr == 0) > AfxMessageBox("pLrSaveStr error!"); > ---------------------------------------------------------- > > And I get the message box. I would suggest you to use DUMPBIN /EXPORTS on the command line or Dependency Walker (depends.exe) http://www.dependencywalker.com/ to check that the DLL actually exports the "lr_save_string" function. Giovanni
From: David Ching on 17 Jan 2010 10:53 "dushkin" <taltene(a)gmail.com> wrote in message news:996d7b1c-7d23-4a09-905e-9a43f215563d(a)e16g2000yqc.googlegroups.com... > Hi, > > For example, I succeed to load lr_message procedure: > ---------------------------------------------------------- > From the DLL h file: > > #if defined(cplusplus) || defined(__cplusplus) > extern "C" { > > #define PROTO(x) x > #endif > > #ifdef _WIN32 > /* LR_FUNC is used for the call-back functions of the compiled Vuser > */ > #define LR_FUNC CALLBACK > /* LR_MSG_FUNC is used for the message functions */ > #define LR_MSG_FUNC WINAPIV > #else > #define LR_FUNC __export WINAPI > #define LR_MSG_FUNC FAR CDECL __export > #endif > > int LR_MSG_FUNC lr_message PROTO((LPCSTR fmt, ...)); > > } > And it is fine. > It is fine because after the preprocessor is run, lr_message has the __export keyword in front of it, so it is actually exported from the DLL. > But, for other functions, on the same DLL I fail. For example: > > > ---------------------------------------------------------- > From the DLL h file: > > int WINAPI lr_save_string PROTO((const char * param_val, const char * > param_name)); > > And I get the message box. > > Why? > Because WINAPI doesn't have __export in the definition and so lr_save_string is not exported. You can use the included utility "DUMPBIN.EXE /exports" which comes with VC++ to actually get a text dump of the exported functions in a DLL. I encourage you to use __declspec(dllexport) for all your exported functions as this is the way modern VC++ does it. A common pattern is in your DLL.H file: #ifdef BUILDING_DLL #define DLLFUNC __declspec(dllexport) #else #define DLLFUNC __declspec(dllimport) and when building the DLL, define BUILDING_DLL in the C++ preprocessor definitions of the project so that those functions are exported. It won't be defined in the .exe using the DLL, so those functions will be imported. (Substitute BUILDING_DLL with a more specific name for your DLL so that all your DLL's have unique names for this and don't all use BUILDING_DLL). -- David
From: Joseph M. Newcomer on 17 Jan 2010 15:15 See below... On Sun, 17 Jan 2010 07:20:15 -0800 (PST), dushkin <taltene(a)gmail.com> wrote: >Hi, > > I am having difficulties to load some procedures from a certain DLL. >While I am able to load couple of them, I fail on some others. > >For example, I succeed to load lr_message procedure: >---------------------------------------------------------- >From the DLL h file: > >#if defined(cplusplus) || defined(__cplusplus) >extern "C" { > >#define PROTO(x) x >#endif > >#ifdef _WIN32 >/* LR_FUNC is used for the call-back functions of the compiled Vuser >*/ >#define LR_FUNC CALLBACK >/* LR_MSG_FUNC is used for the message functions */ >#define LR_MSG_FUNC WINAPIV >#else >#define LR_FUNC __export WINAPI >#define LR_MSG_FUNC FAR CDECL __export >#endif **** You have not stated the purpose of any of this. Are you still suppporting 16-bit Windows? Note that the standard technique for using a common header file is to say #ifdef _SOME_UNIQUE_ID_HERE_PROBABLY_WITH_A_GUID #define LIBDEF declspec(dllexport) #else #define LIBDEF #endif ....stuff #undef LIBDEF (you can use any name you want, I happen to like LIBDEF) Then, in compiling your DLL, you #define that unique ID before doing your #include, and of course your clients would never define it. So I don't know what this is trying to accomplish. I don't see that it does anything interesting. **** > >int LR_MSG_FUNC lr_message PROTO((LPCSTR fmt, ...)); > >} >---------------------------------------------------------- > >In my h file: > >typedef int (*LR_MESSAGE)(LPCSTR fmt, ...); >LR_MESSAGE pLrMessage; > >---------------------------------------------------------- > >In my cpp file: > > pLrMessage = 0; > pLrMessage = (LR_MESSAGE)GetProcAddress(m_hIrun, "lr_message"); > if (pLrMessage == 0) > AfxMessageBox("pLrMessage error!"); > > >---------------------------------------------------------- > >And it is fine. > >But, for other functions, on the same DLL I fail. For example: > > >---------------------------------------------------------- >From the DLL h file: > >int WINAPI lr_save_string PROTO((const char * param_val, const char * >param_name)); **** WINAPI is __stdcall, so the names are not _name, but _name@n for n being the number of parameter bytes being passed. It would be inappropriate to use __stdcall if you plan to use GetProcAddress as you show it. So you have the wrong symbol name. Don't use WINAPI. Besides, why are you specifying this has a linkage type that is the same as a kernel call? That's what WINAPI means; you should not be defining user functions using the WINAPI keyword because you are not implementing kernel calls. It is not appropriate to search for something that has the #define you want and choose that without realizing the implications. WINAPI is subject to Change Without Notice in going to a different platform. It is a very, very poor choice here. > >---------------------------------------------------------- > >In my h file: > >typedef int (*LR_SAVE_STRING)(const char *param_value, const char >*param_name); **** Either you are supporting 16-bit Windows, or you aren't. If you are, this should be LPCSTR, not const char *. If you are not supporting 16-bit Windows, it is questionable why you are using the obsolete char data type for anything. Note that in Win16, this should be declared as a FAR pointer. If you are not supporting WIn16, you should never, ever, under any conditions imaginable, use the word FAR anywhere! Sadly, although this pseudo-keyword has been obsolete in Win32 since its creation, it has not been removed from many header files (nobody knows why, as far as I can tell). It doesn't mean that it makes sense to use it. ***** > >LR_SAVE_STRING pLrSaveStr; >---------------------------------------------------------- > >In my cpp file: > > pLrSaveStr = 0; > pLrSaveStr = (LR_SAVE_STRING)GetProcAddress(m_hIrun, >"lr_save_string"); **** I would try "lr_save_string@8" as the name, since that is what it is. Better still, use CDECL for any function you export from a DLL! **** > if (pLrSaveStr == 0) > AfxMessageBox("pLrSaveStr error!"); >---------------------------------------------------------- > >And I get the message box. > >Why? **** Because, as I pointed out, you used the wrong name. joe **** > >Thanks! Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: dushkin on 18 Jan 2010 02:37
On Jan 17, 10:15 pm, Joseph M. Newcomer <newco...(a)flounder.com> wrote: > See below... > > > > On Sun, 17 Jan 2010 07:20:15 -0800 (PST), dushkin <talt...(a)gmail.com> wrote: > >Hi, > > > I am having difficulties to load some procedures from a certain DLL. > >While I am able to load couple of them, I fail on some others. > > >For example, I succeed to load lr_message procedure: > >---------------------------------------------------------- > >From the DLL h file: > > >#if defined(cplusplus) || defined(__cplusplus) > >extern "C" { > > >#define PROTO(x) x > >#endif > > >#ifdef _WIN32 > >/* LR_FUNC is used for the call-back functions of the compiled Vuser > >*/ > >#define LR_FUNC CALLBACK > >/* LR_MSG_FUNC is used for the message functions */ > >#define LR_MSG_FUNC WINAPIV > >#else > >#define LR_FUNC __export WINAPI > >#define LR_MSG_FUNC FAR CDECL __export > >#endif > > **** > You have not stated the purpose of any of this. Are you still suppporting 16-bit Windows? > > Note that the standard technique for using a common header file is to say > > #ifdef _SOME_UNIQUE_ID_HERE_PROBABLY_WITH_A_GUID > #define LIBDEF declspec(dllexport) > #else > #define LIBDEF > #endif > ...stuff > > #undef LIBDEF > > (you can use any name you want, I happen to like LIBDEF) > > Then, in compiling your DLL, you #define that unique ID before doing your #include, and of > course your clients would never define it. > > So I don't know what this is trying to accomplish. I don't see that it does anything > interesting. > **** > > > > >int LR_MSG_FUNC lr_message PROTO((LPCSTR fmt, ...)); > > >} > >---------------------------------------------------------- > > >In my h file: > > >typedef int (*LR_MESSAGE)(LPCSTR fmt, ...); > >LR_MESSAGE pLrMessage; > > >---------------------------------------------------------- > > >In my cpp file: > > > pLrMessage = 0; > > pLrMessage = (LR_MESSAGE)GetProcAddress(m_hIrun, "lr_message"); > > if (pLrMessage == 0) > > AfxMessageBox("pLrMessage error!"); > > >---------------------------------------------------------- > > >And it is fine. > > >But, for other functions, on the same DLL I fail. For example: > > >---------------------------------------------------------- > >From the DLL h file: > > >int WINAPI lr_save_string PROTO((const char * param_val, const char * > >param_name)); > > **** > WINAPI is __stdcall, so the names are not _name, but _name@n for n being the number of > parameter bytes being passed. It would be inappropriate to use __stdcall if you plan to > use GetProcAddress as you show it. So you have the wrong symbol name. Don't use WINAPI. > Besides, why are you specifying this has a linkage type that is the same as a kernel call? > That's what WINAPI means; you should not be defining user functions using the WINAPI > keyword because you are not implementing kernel calls. > > It is not appropriate to search for something that has the #define you want and choose > that without realizing the implications. WINAPI is subject to Change Without Notice in > going to a different platform. It is a very, very poor choice here. > > >---------------------------------------------------------- > > >In my h file: > > >typedef int (*LR_SAVE_STRING)(const char *param_value, const char > >*param_name); > > **** > Either you are supporting 16-bit Windows, or you aren't. If you are, this should be > LPCSTR, not const char *. If you are not supporting 16-bit Windows, it is questionable > why you are using the obsolete char data type for anything. > > Note that in Win16, this should be declared as a FAR pointer. If you are not supporting > WIn16, you should never, ever, under any conditions imaginable, use the word FAR anywhere! > > Sadly, although this pseudo-keyword has been obsolete in Win32 since its creation, it has > not been removed from many header files (nobody knows why, as far as I can tell). It > doesn't mean that it makes sense to use it. > ***** > > >LR_SAVE_STRING pLrSaveStr; > >---------------------------------------------------------- > > >In my cpp file: > > > pLrSaveStr = 0; > > pLrSaveStr = (LR_SAVE_STRING)GetProcAddress(m_hIrun, > >"lr_save_string"); > > **** > I would try "lr_save_string@8" as the name, since that is what it is. Better still, use > CDECL for any function you export from a DLL! > ****> if (pLrSaveStr == 0) > > AfxMessageBox("pLrSaveStr error!"); > >---------------------------------------------------------- > > >And I get the message box. > > >Why? > > **** > Because, as I pointed out, you used the wrong name. > joe > > **** > > >Thanks! > > Joseph M. Newcomer [MVP] > email: newco...(a)flounder.com > Web:http://www.flounder.com > MVP Tips:http://www.flounder.com/mvp_tips.htm Joe, the @ was the solution! The DLL is not mine. It is a commercial DLL which was designed probably to support 16bit. So I managed to the procedures pointers by adding the number of parameter size to their name. Thanks! |