Can anyone tell me how to export a friend function
of an exported class within a DLL ?
Although friend functions are declared within a class,
they are not class member functions, hence specifying
__declspec( dllexport ) before the class name, such as:
class __declspec( dllexport ) MyInt
{
friend ostream& operator<<( ostream& os, MyInt& s );
public:
MyInt( int iP ) : i( iP ) {}
private:
int i;
};
does not export the friend function. This was evident to me
in the following linker error I got trying to link my DLL.
main.obj : error LNK2001: unresolved external symbol "class ostream &
__cdecl operator<<(class ostream &,class MyInt &)"
(??6@YAAAVostream@@AAV0@AAVMyInt@@@Z)
Debug/DLL_exe.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
DLL_exe.exe - 2 error(s), 1 warning(s)
// myfile.h
class __declspec(dllexport) MyClass
{
friend void __declspec(dllexport) myFriend();
public:
};
// myfile.cpp
void __declspec(dllexport) myFriend()
{
}
Les
*** Reply email address: nospam-l...@mindspring.com
Larry wrote in message <351B1A...@erols.com>...
Thanks for your reply.
I had already tried many combinations including the one you
suggested. I noticed when I run DUMPBIN /EXPORTS on the dll
file, it does not show the friend function. I will include
my library code and the executable code that links that library;
I would be very greatful if you could take more time to help me.
-------------------------------------------------------------------
My Library header (lib.h):
#define DllImport __declspec( dllimport )
#define DllExport __declspec( dllexport )
#ifdef _EXPORTING
#define DllImpExp __declspec( dllexport )
#else
#define DllImpExp __declspec( dllimport )
#endif
void DllImpExp func( int i );
class DllImpExp MyInt
{
friend ostream& DllImpExp operator<<( ostream& os, MyInt& s );
public:
MyInt( int iP ) : i( iP ) {}
private:
int i;
};
-------------------------------------------------------------------
My library implementation file (lib.cpp):
#include <iostream.h>
#define _EXPORTING
#include "lib.h"
void DllExport func( int i )
{
cout << "func: i = " << i << endl;
};
ostream& DllExport operator<<( ostream& os, MyInt& s )
{
os << s << endl;
return os;
}
-------------------------------------------------------------------
My exe implementation file (main.cpp):
#include <iostream.h>
#include "lib.h"
main()
{
MyInt m( 3 );
cout << m;
func( 5 );
return 0;
}
-------------------------------------------------------------------
DUMPBIN of lib.dll:
E:\C++ Projects\_lib>dumpbin /exports DLL_lib.dll
Microsoft (R) COFF Binary File Dumper Version 5.00.7022
Copyright (C) Microsoft Corp 1992-1997. All rights reserved.
Dump of file lib.dll
File Type: DLL
Section contains the following Exports for lib.dll
0 characteristics
351C9948 time date stamp Sat Mar 28 01:31:36 1998
0.00 version
1 ordinal base
3 number of functions
3 number of names
ordinal hint name
1 0 ??0MyInt@@QAE@H@Z (00001014)
2 1 ??4MyInt@@QAEAAV0@ABV0@@Z (00001019)
3 2 ?func@@YAXH@Z (00001023)
Summary
7000 .data
1000 .idata
3000 .rdata
2000 .reloc
1D000 .text
-------------------------------------------------------------------
End of long message (sorry)...
>class DllImpExp MyInt
>{
> friend ostream& DllImpExp operator<<( ostream& os, MyInt& s );
>
-- Sorry, my mistake: it should say:
friend DllImpExp ostream & operator <<(ostream&....
*NOT*
friend ostream & DllImpExp operator << (ostream&...
IMHO, the compiler should have complained about the former, since
__declspec()
is part of the decl-specifier in the C++ grammar, not part of the
declarator, and thus should
always come before the return type.
-- By the way, the following construct, while it works fine if your DLL's
don't ever reference
each other, will become a problem when they do. If DLL_1 references
functions defined
by DLL_2, and both use the macro _EXPORTING, the linker will expect both
DLL's to
define the functions exported by DLL_1.
>#ifdef _EXPORTING
>#define DllImpExp __declspec( dllexport )
>#else
>#define DllImpExp __declspec( dllimport )
>#endif
The best solution I know of for this is to define a custom macro for each
DLL like this:
#if (PROJECTNAME="DLL_1")
#define IMPEXP_DLL1 __declspec(dllexport)
#else
#define IMPEXP_DLL1 __declspec(dllimport)
#endif
Then, in the DLL_1 project build settings, under the C++ / Preprocessor
category, add a definition
for PROJECTNAME="DLL_1". Thus any other DLL's which import DLL_1 won't get
confused.
This method has another beneficial side-effect: since each macro contains
the name of the DLL
which exports the symbol, it is much easier when sifting through a lot of
header files to remember
which DLL contains the implementation for any name.
Good luck,
Les