From: dushkin on
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
"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
"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
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
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!