Hi,

I have created a dll project using app wizard. It created the
dll_w32_export.h file as below:
----------------------------------------------
#ifdef DLL_W32_EXPORT_EXPORTS
#define DLL_W32_EXPORT_API __declspec(dllexport)
#else
#define DLL_W32_EXPORT_API __declspec(dllimport)
#endif

// This class is exported from the dll_w32_export.dll
class DLL_W32_EXPORT_API CDll_w32_export {
public:
CDll_w32_export(void);
// TODO: add your methods here.
};

extern DLL_W32_EXPORT_API int nDll_w32_export;

DLL_W32_EXPORT_API int fnDll_w32_export(void);
------------------------
My app code segement is:
int ret;
int OldErrMode;
HANDLE hDll;

// load dll
// set err mode to let app handle critical errors
OldErrMode = SetErrorMode (SEM_FAILCRITICALERRORS);
hDll = LoadLibrary ("dll_w32_export.dll");
SetErrorMode (OldErrMode);

if (!hDll)
{
ErrorNotify (IDS_LOADLIBFAILED);
return 1;
}

ret = fnDll_w32_export();
-------------------------------------
First I got link error:
error LNK2001: unresolved external symbol "__declspec(dllimport) int __cdecl
fnDll_w32_export(void)" (__imp_?fnDll_w32_export@@YAHXZ)

Then I added #define DLL_W32_EXPORT_EXPORTS

Now I get the error:
error LNK2001: unresolved external symbol "int __cdecl
fnDll_w32_export(void)" (?fnDll_w32_export@@YAHXZ)

What am I missing?

ThanQ...

Re: DLL declarations created by VC++ app wizard by Norbert

Norbert
Wed Dec 12 13:37:27 PST 2007



SME schrieb:
> Hi,
>
> I have created a dll project using app wizard. It created the
> dll_w32_export.h file as below:
> ----------------------------------------------
> #ifdef DLL_W32_EXPORT_EXPORTS
> #define DLL_W32_EXPORT_API __declspec(dllexport)
> #else
> #define DLL_W32_EXPORT_API __declspec(dllimport)
> #endif
>
> // This class is exported from the dll_w32_export.dll
> class DLL_W32_EXPORT_API CDll_w32_export {
> public:
> CDll_w32_export(void);
> // TODO: add your methods here.
> };
>
> extern DLL_W32_EXPORT_API int nDll_w32_export;
>
> DLL_W32_EXPORT_API int fnDll_w32_export(void);
> ------------------------
> My app code segement is:
> int ret;
> int OldErrMode;
> HANDLE hDll;
>
> // load dll
> // set err mode to let app handle critical errors
> OldErrMode = SetErrorMode (SEM_FAILCRITICALERRORS);
> hDll = LoadLibrary ("dll_w32_export.dll");
> SetErrorMode (OldErrMode);
>
> if (!hDll)
> {
> ErrorNotify (IDS_LOADLIBFAILED);
> return 1;
> }
>
> ret = fnDll_w32_export();
> -------------------------------------
> First I got link error:
> error LNK2001: unresolved external symbol "__declspec(dllimport) int __cdecl
> fnDll_w32_export(void)" (__imp_?fnDll_w32_export@@YAHXZ)
>
> Then I added #define DLL_W32_EXPORT_EXPORTS
>
> Now I get the error:
> error LNK2001: unresolved external symbol "int __cdecl
> fnDll_w32_export(void)" (?fnDll_w32_export@@YAHXZ)
>
> What am I missing?

You are missing several things:

You need to #define DLL_W32_EXPORT_EXPORTS in your DLL project (when creating
the DLL), not in your application project. This makes the linker export the
class and the public symbols. It means that the classes functions and the
publich functions and variables are put into the DLL's export table and to the
import library file.

In your application, include the dll_w32_export.h without defining the
DLL_W32_EXPORT_EXPORTS.

Link the application against the dll_w32_export.lib file which is created when
linking the DLL. It is the DLL's import library that the linker generates when
linking the DLL.

Believe me, you do not want to dynamically load the DLL at runtime with
LoadLibrary. By linking the application against the DLL's import library you
tell windows to autimatically load the DLL when the application is started.

Norbert

Re: DLL declarations created by VC++ app wizard by SME

SME
Wed Dec 12 15:32:07 PST 2007

You are asking me to 'Load the DLL imlicitly'. I have tried it and works
fine. For that I don't have to do any changes to what the App Wizard had
created.

I want to test loading it explicitly / dynamically as eventually I will be
using it with a VB6 program. If I want to load it explicitly, then I
shouldn't link with the .lib. The sequence of operations as per the help doc
is:

1. Call LoadLibrary and get the handle - I get it, no problem.
2. Call GetProcAddress to get the pointer to the external function. - I
realized this after posting the original problem. I do fial on this. The
call is not succeeding.
3. Call the external function - This fails in linking itself, as the errors
that I presented.
4. Call FreeLibrary after finishing with it - I get it, no problem.

I have gone through "DLLs in Win32" on MSDN / VS Help. It talks of a sample
program "PortTool". It talks about defining a Function Table, a .DEF file.
The sample program doesn't have any call to LoadLibrary or FreeLibrary. I
didn't find any .DEF file for it. I tried using the Function Table as
described here, but in vain. Even the DLLTRACE is not following what is
preached in these docs. I think, they all doing a Implicit Linking to the
dll.

ThanQ...

"Norbert Unterberg" <nunterberg@newsgroups.nospam> wrote in message
news:%234RSycQPIHA.5184@TK2MSFTNGP05.phx.gbl...
>
>
> SME schrieb:
>> Hi,
>>
>> I have created a dll project using app wizard. It created the
>> dll_w32_export.h file as below:
>> ----------------------------------------------
>> #ifdef DLL_W32_EXPORT_EXPORTS
>> #define DLL_W32_EXPORT_API __declspec(dllexport)
>> #else
>> #define DLL_W32_EXPORT_API __declspec(dllimport)
>> #endif
>>
>> // This class is exported from the dll_w32_export.dll
>> class DLL_W32_EXPORT_API CDll_w32_export {
>> public:
>> CDll_w32_export(void);
>> // TODO: add your methods here.
>> };
>>
>> extern DLL_W32_EXPORT_API int nDll_w32_export;
>>
>> DLL_W32_EXPORT_API int fnDll_w32_export(void);
>> ------------------------
>> My app code segement is:
>> int ret;
>> int OldErrMode;
>> HANDLE hDll;
>>
>> // load dll
>> // set err mode to let app handle critical errors
>> OldErrMode = SetErrorMode (SEM_FAILCRITICALERRORS);
>> hDll = LoadLibrary ("dll_w32_export.dll");
>> SetErrorMode (OldErrMode);
>>
>> if (!hDll)
>> {
>> ErrorNotify (IDS_LOADLIBFAILED);
>> return 1;
>> }
>>
>> ret = fnDll_w32_export();
>> -------------------------------------
>> First I got link error:
>> error LNK2001: unresolved external symbol "__declspec(dllimport) int
>> __cdecl fnDll_w32_export(void)" (__imp_?fnDll_w32_export@@YAHXZ)
>>
>> Then I added #define DLL_W32_EXPORT_EXPORTS
>>
>> Now I get the error:
>> error LNK2001: unresolved external symbol "int __cdecl
>> fnDll_w32_export(void)" (?fnDll_w32_export@@YAHXZ)
>>
>> What am I missing?
>
> You are missing several things:
>
> You need to #define DLL_W32_EXPORT_EXPORTS in your DLL project (when
> creating the DLL), not in your application project. This makes the linker
> export the class and the public symbols. It means that the classes
> functions and the publich functions and variables are put into the DLL's
> export table and to the import library file.
>
> In your application, include the dll_w32_export.h without defining the
> DLL_W32_EXPORT_EXPORTS.
>
> Link the application against the dll_w32_export.lib file which is created
> when linking the DLL. It is the DLL's import library that the linker
> generates when linking the DLL.
>
> Believe me, you do not want to dynamically load the DLL at runtime with
> LoadLibrary. By linking the application against the DLL's import library
> you tell windows to autimatically load the DLL when the application is
> started.
>
> Norbert



Re: DLL declarations created by VC++ app wizard by Igor

Igor
Wed Dec 12 15:49:35 PST 2007

SME <smelchuri@hotmail.com> wrote:
> You are asking me to 'Load the DLL imlicitly'. I have tried it and
> works fine. For that I don't have to do any changes to what the App
> Wizard had created.
>
> I want to test loading it explicitly / dynamically as eventually I
> will be using it with a VB6 program.

For that, you need to export plain C API - a set of standalone functions
(similar to how Win32 API does it). VB wouldn't know what to do with a
C++ class.

Even from a C++ client, using LoadLibrary/GetProcAddress on an exported
class, while possible, is completely impractical. The DLL doesn't really
export a class - it exports each method, as well as constructors and
destructors, as a standalone function with a weird name.

Alternatively, make your DLL a COM server - it's much easier to use from
VB than C API.

> If I want to load it explicitly,
> then I shouldn't link with the .lib. The sequence of operations as
> per the help doc is:
>
> 1. Call LoadLibrary and get the handle - I get it, no problem.
> 2. Call GetProcAddress to get the pointer to the external function. -
> I realized this after posting the original problem. I do fial on
> this. The call is not succeeding.

You are likely using a wrong name. Use Dependency Walker
(http://www.dependencywalker.com/) to examine functions actually
exported by the DLL, see what kind of names they are exported under. But
really, abandon this idea, it's not workable.

> 3. Call the external function - This fails in linking itself, as the
> errors that I presented.

I don't understand. You are supposed to call through a function pointer
obtained by GetProcAddress. Linker is not involved in this.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925



Re: DLL declarations created by VC++ app wizard by SME

SME
Wed Dec 12 20:28:16 PST 2007

Thanks Igor.

Hmm, then I have to learn how COM server works also.

However the actual function name exported is present in the error message
that I had given in my original post. Getting the address of that function,
was running.

Appending of a random unique code to a sensible function name appears to be
absurd. Why it was done? There was no mention of that in any of the help
docs. That's cheating. So there must a decent way to reclaim the original
function names. Probably the "Function Table" method must be working better.
But I don't think the help docs were mentioning this method as an method of
convinience rather than saying that is the way to do. Also the help doc
"DLLs in Wind32" talks about some .DEF files in its example code. How to
creat this .DEF file? When I added a .DEF file and added "exports ..." the
compiler said "exports" is not valid for the platform so ignored it. What is
this?

Actually I tried that method also but in vain. I will try it again.

ThanQ...

"Igor Tandetnik" <itandetnik@mvps.org> wrote in message
news:%23Eh9nmRPIHA.1184@TK2MSFTNGP04.phx.gbl...
> SME <smelchuri@hotmail.com> wrote:
>> You are asking me to 'Load the DLL imlicitly'. I have tried it and
>> works fine. For that I don't have to do any changes to what the App
>> Wizard had created.
>>
>> I want to test loading it explicitly / dynamically as eventually I
>> will be using it with a VB6 program.
>
> For that, you need to export plain C API - a set of standalone functions
> (similar to how Win32 API does it). VB wouldn't know what to do with a C++
> class.
>
> Even from a C++ client, using LoadLibrary/GetProcAddress on an exported
> class, while possible, is completely impractical. The DLL doesn't really
> export a class - it exports each method, as well as constructors and
> destructors, as a standalone function with a weird name.
>
> Alternatively, make your DLL a COM server - it's much easier to use from
> VB than C API.
>
>> If I want to load it explicitly,
>> then I shouldn't link with the .lib. The sequence of operations as
>> per the help doc is:
>>
>> 1. Call LoadLibrary and get the handle - I get it, no problem.
>> 2. Call GetProcAddress to get the pointer to the external function. -
>> I realized this after posting the original problem. I do fial on
>> this. The call is not succeeding.
>
> You are likely using a wrong name. Use Dependency Walker
> (http://www.dependencywalker.com/) to examine functions actually exported
> by the DLL, see what kind of names they are exported under. But really,
> abandon this idea, it's not workable.
>
>> 3. Call the external function - This fails in linking itself, as the
>> errors that I presented.
>
> I don't understand. You are supposed to call through a function pointer
> obtained by GetProcAddress. Linker is not involved in this.
> --
> With best wishes,
> Igor Tandetnik
>
> With sufficient thrust, pigs fly just fine. However, this is not
> necessarily a good idea. It is hard to be sure where they are going to
> land, and it could be dangerous sitting under them as they fly
> overhead. -- RFC 1925
>
>



Re: DLL declarations created by VC++ app wizard by Igor

Igor
Wed Dec 12 20:52:40 PST 2007

"SME" <smelchuri@hotmail.com> wrote in message
news:uALJWCUPIHA.536@TK2MSFTNGP06.phx.gbl
> However the actual function name exported is present in the error
> message that I had given in my original post.

No - the error message is about a function that you declared in the
client (for reasons unclear to me) and never implemented (hence linker
complains). It has nothing to do whatsoever with the function name as
exported from the server (which the linker knows nothing about, since
you insist on linking dynamically at run time).

> Getting the address of
> that function, was running.

What do you mean, "was running"? Your program failed to compile, let
alone run.

> Appending of a random unique code to a sensible function name appears
> to be absurd. Why it was done?

http://en.wikipedia.org/wiki/Name_mangling

There is no random code involved. Whatever gave you the idea?

> There was no mention of that in any of
> the help docs.

http://msdn2.microsoft.com/en-us/library/56h2zst2.aspx
http://support.microsoft.com/kb/126845

> Also the help doc "DLLs in Wind32" talks about
> some .DEF files in its example code. How to creat this .DEF file?

By using your head, your fingers, your keyboard and your favorite text
editor.

> When I added a .DEF file and added "exports ..." the compiler said
> "exports" is not valid for the platform so ignored it. What is this?

Show the exact text of the message, complete with the error number
(looks like LNK1234)

But I repeat - exporting C++ classes from a DLL and hoping to bind to
them dynamically, with LoadLibrary and GetProcAddress, is not going to
work. It's hopeless. Give up now, don't waste your time. Spend it
instead learning one of the two approaches that are known to work.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925



Re: DLL declarations created by VC++ app wizard by Ben

Ben
Thu Dec 13 07:28:54 PST 2007

> Appending of a random unique code to a sensible function name appears to
> be absurd. Why it was done? There was no mention of that in any of the
> help

C++ classes are not portable between languages, so the compiler can use any
name it pleases.

However when you export a global function, it is language independent, and
the name will be quite nicely defined.
To do that from C++, use

extern "C" __stdcall Func(Args) { ... }

or

extern "C" __cdecl Func(Args) { ... }

The first version appends a suffix which is the number of bytes on the stack
used for arguments and removed by the function. The second version just
prefixes with an underscore. The prefix or suffix can be removed completely
using a module definition file (although then the caller could use the wrong
calling convention).



Re: DLL declarations created by VC++ app wizard by SME

SME
Sun Dec 16 15:52:14 PST 2007

As of now I just want to call one or two functions in my DLL from a VB
program. So I am not going for COM.

However your link for "Dependency Walker" was quite helpful and that did
resolve my issue.

And finally, I have got the DLL function from a VB program.

ThanQ...

"Igor Tandetnik" <itandetnik@mvps.org> wrote in message
news:%23pTe$PUPIHA.5400@TK2MSFTNGP04.phx.gbl...
> "SME" <smelchuri@hotmail.com> wrote in message
> news:uALJWCUPIHA.536@TK2MSFTNGP06.phx.gbl
>> However the actual function name exported is present in the error
>> message that I had given in my original post.
>
> No - the error message is about a function that you declared in the client
> (for reasons unclear to me) and never implemented (hence linker
> complains). It has nothing to do whatsoever with the function name as
> exported from the server (which the linker knows nothing about, since you
> insist on linking dynamically at run time).
>
>> Getting the address of
>> that function, was running.
>
> What do you mean, "was running"? Your program failed to compile, let alone
> run.
>
>> Appending of a random unique code to a sensible function name appears
>> to be absurd. Why it was done?
>
> http://en.wikipedia.org/wiki/Name_mangling
>
> There is no random code involved. Whatever gave you the idea?
>
>> There was no mention of that in any of
>> the help docs.
>
> http://msdn2.microsoft.com/en-us/library/56h2zst2.aspx
> http://support.microsoft.com/kb/126845
>
>> Also the help doc "DLLs in Wind32" talks about
>> some .DEF files in its example code. How to creat this .DEF file?
>
> By using your head, your fingers, your keyboard and your favorite text
> editor.
>
>> When I added a .DEF file and added "exports ..." the compiler said
>> "exports" is not valid for the platform so ignored it. What is this?
>
> Show the exact text of the message, complete with the error number (looks
> like LNK1234)
>
> But I repeat - exporting C++ classes from a DLL and hoping to bind to them
> dynamically, with LoadLibrary and GetProcAddress, is not going to work.
> It's hopeless. Give up now, don't waste your time. Spend it instead
> learning one of the two approaches that are known to work.
> --
> With best wishes,
> Igor Tandetnik
>
> With sufficient thrust, pigs fly just fine. However, this is not
> necessarily a good idea. It is hard to be sure where they are going to
> land, and it could be dangerous sitting under them as they fly
> overhead. -- RFC 1925
>