Solved

friends and dllexport in VC++5

Posted on 1998-12-06
31
1,273 Views
Last Modified: 2008-02-26
Is there a known problem with dllexporting and dllimporting friend functions of classes in VC++5?

I have a class with some protected members, and I declared a friend function therein to overload the operator<< for ostream. The whole class is properly dllexported. The operator<< is defined as a class-independent function:

headerfile:

class _DLL_ A {
protected:
  int a;
public:
  friend ostream & operator<<(ostream & s, A & obj);
};

implementation:

ostream & operator<<(ostream & s, A & obj) {
  return s << obj.a;
}

When I try to use this function within the DLL, everything is fine, but when I move outside the DLL and call it from an exe that includes the dll as dynamically linked library, I get a LNK2001 linker error, namely that the function is declared but not defined. what's going on?
0
Comment
Question by:MaDdUCK
  • 16
  • 12
  • 3
31 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1179402
No, I don't think there is a problem with this.  The problem probably is that the << operator is declared only in the exported class declaration, but is not exported.  

continues.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179403
For example, if you have a header file that does

__declspec(DllExport) class SomeClass
{
   friend ostream & operator<<(ostream & s, SomeClass & obj);
};

This does not declare the ostream operator as an exported function (I think.  Now I'm beginning to to regret answering as I realize that this is not something I'm possitive of.)  I think you need to do one of two things either

__declspec(DllExport) class SomeClass
{
   friend _declspec(DllExport) ostream & operator<<(ostream & s, SomeClass & obj);
};

or

__declspec(DllExport) class SomeClass
{
   friend ostream & operator<<(ostream & s, SomeClass & obj);
};

_declspec(DllExport) ostream & operator<<(ostream & s, SomeClass & obj);

should declare the operator as an exported function.  I'm going on intuition here, but the way it is documented is that applying the _declspec(DllExport) to a class is the same as applying it to the members.  Thus, since the >> operator is not a member, the _declspec is not applied to it.  Thus you need to explicitly declare it as exported.  Give it a try and let me know if it doesn't work.
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179404
about your last point:
other member functions of the class are exported flawlessly, it is just the friends...why?
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179405
and it did not fix the problem either...
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179406
That was my last point.  The friends are not members.  If you declare a class as beign exported, it exports the member functions of the class.  But friend functions are not member functions.  So they must be exported seperately.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179407
I'm still suspiscios, can you post your header code?
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179408
header:
=======

/*
_DLL_ is defined to be
 - __declspec(dllimport) if the header is included outside the DLL
 - __declspec(dllexport) if the header is included inside the DLL
*/

//...

class _DLL_ Tag {
protected:
      bool const single;
//...
            
public:
//...
      friend std::ostream & operator<<(std::ostream & s, mdHtml::Tag & t);
};

//...

std::ostream & _DLL_ operator<<(std::ostream & s, Tag & t);

//...

implementation:
===============

//...

std::ostream & _DLL_ operator<<(std::ostream & s, Tag & t)
{
        // bitshift some protected members of the class onto s.
      return s;
}

//...

is this clear?

0
 
LVL 22

Expert Comment

by:nietod
ID: 1179409
It is clear.  But you must be making some mistake that is not in your example (you've edited it.)  I have a working example.  I'll post mine for what it is worth.  If that doesn't help, you can e-mail me yours.  (nietod@theshop.net).
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179410
**********MADAPP.CPP**************
#include "maddll\maddll.h"
#include <fstream.h>
#include <windows.h>

int PASCAL    WinMain(
                HANDLE hInstance,        // Instance handle
                HANDLE hPrevInstance,    // Previous instance handle
                LPSTR lpszCommandLine,   // Command line string
                int cmdShow )        
{
   Cls A;
   fstream F;

   F << A;
   return 0;
};
*************MADDLL.H************
#ifndef _maddll
#define _maddll
#include <iostream.h>

#ifndef ExpMadDll
#define ExpMadDll _declspec(dllimport)
#endif

class ExpMadDll Cls
{
private:
   int i;
public:
   Cls();
   friend ExpMadDll ostream & operator<<(ostream & s,const Cls &c);  //******
};

#endif
**************MADDLL.CPP***************
#define ExpMadDll _declspec(dllexport)
#include "maddll.h"

Cls::Cls()
{
   i = 5;
}

ostream & __declspec(dllexport) operator<<(ostream & s,const Cls &c)
{
   s << c.i;
   return s;
}
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179411
Be aware of an inadvertant overloads.  For example, in your .header file you declare the 2nd parameter to the << operator as non-const.  (That is unusual)  Do you declare it the same way in your Dll's source code?
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179412
I'll email them to you once I cleaned up the files a little.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179413
I'm about done for the day.  I'll be back in about 11 hours.
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179414
what is so hard to compile it? if everything fails, then extract the zip to \web\SCPCS 2.0\ of a drive and subst j: <the drive> to simulate the proper paths (or put it into j:\web\SCPCS 2.0 if you have a j: drive. Then this should work. There are a couple of path refs inside the code, but these are not evaluated until run-time...)
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179415
Well one problem is that you had long file names in there and my version of pkzip screws up the names.  But I'll get to it today.  I have one more thing to do first.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179416
Well I finaly got it open, but I can't seem to compile it.  The problem I'm getting is that Row_Class is undefined when you create a vector<> of it.  (First you define the vector and then you define the template.  However my attempt to be move things around have produced more problems.  (I don't have a good handle on you orginization--and I had to dissable my CD (drive j) to do this and I am very impacient without my music!.)

Why would I be getting this problem whn you don't?  You don't right?
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179417
tried a dummy declare of
class Row_Class;
before the vector declaration?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179418
A dummy won't do it.  It is verifying the class has the right members, operators constructors etc.  Since it doesn't know what the class is it assumes it is an int and then runs into problems.  If I move the class definiton before that I get other problems.  I can't image why I am getting this and you aren't.
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179419
which module is this in?

I spent a couple of hours restructuring some of the moddules because I did not like them. I will put a new project up soon, so how about you give me a path where you would like the project to sit on your hdd so that you can easily download and run it without stopping your music. I will see whether I can tweak it so it will run no probs at yours.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179420
I get the error when compiling error.cpp--the first file it tries.  

The path doesn't matter but drive D would be nice.  or drives after K.  But at the moment I do have it so I can access j as my hard disk so if that is a problem leave it as it is.


0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179421
did you get nmy email?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179422
Yes, but I'm having trouble getting to the FTP site.  I tried this morning and again about 1/2 hour ago.  It seemed like the problem was on you end, like your server was down.  Is there a problem?
0
 
LVL 1

Expert Comment

by:The_Brain
ID: 1179423
I would really just avoid using friend, there are disputes about its use, and a later version may drop it.  

Have you actually got a constructor? destructor.  I think that is the problem.
0
 
LVL 1

Expert Comment

by:The_Brain
ID: 1179424
Have you actually got a constructor? destructor.  I think that is the problem. Initialise your variables as well.


I would really just avoid using friend, there are disputes about its use, and a later version may drop it.  

0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179425
I have constructors and destructors. The class works fine in one unit, but the DLL export and import is causing the problem.

And I have not heard anything about the friend thingy yet. Do you have a site with additional info by any chance?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179426
No later version of c++ will drop "friend"--ever.  The standards committee worked increadibly hard to maintain compatiblilty with legacy C code, don't you think they want to maintain compatibility with a greater quantity of C++ code?  Not to mention that friend is increadibly important.

I will look at the code a little later this morning.
0
 
LVL 1

Expert Comment

by:The_Brain
ID: 1179427
Ok in that case nietod, I suppose that it is safe to use friends?
Well ok then.  Link errors occurs when there is a mismatch of protocols and their functions.  Just look at that maybe, I can't see anything like that in the code, but I think it is worth a look.
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179428
It seems as moving the __declspec(dllxxport) to the front of the lines fixed
the problem (don't move it for classes, i.e. a class should still be
declared as 'class __declspec(dlllexport) classname {')

nietod: thanks so much. I've upped the points to 250 (don't have much more, but if you feel like you deserve more, then I shall purchase some!)
please answer it then!
0
 
LVL 22

Accepted Solution

by:
nietod earned 350 total points
ID: 1179429
You're welcome.

I of course FEEL I deserve more, but as you are in the market for VC 6, you had better save your pennies.  There was a time when Microsoft's development products were being given away to encourage windows development.  Not any more...
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179430
350...
because you were so nice...
0
 
LVL 22

Expert Comment

by:nietod
ID: 1179431
you're gonna spoil me...
0
 
LVL 8

Author Comment

by:MaDdUCK
ID: 1179432
:-9 whatever...
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now