Solved

friends and dllexport in VC++5

Posted on 1998-12-06
31
1,337 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

688 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