tags:

views:

258

answers:

2

Okay guys, this is a follow up to one of my previous questions and I have come up with a possible solution to my project and I need some advice or guidance if I have this right.

Basically my project is a library to be used and compiled on both Linux and Windows, the Linux part isn't much of an issue, its Windows.

My library consists mainly of classes so 95% of C++ code. In order to provide better support and avoid name mangling issues I'm going to be using interfaces and factory methods to get instances of those classes rather than calling it directly. I will also use extern "C" on the factory functions ONLY to avoid name mangling.

Please bare with me I have a few questions and wasn't sure to post it as separate questions or combine it as they are related.

So here are the questions:

  1. I will use the export/import macros on the factory functions but do I then need to add the export/import (__declspec(dllexport/import)) on the header files of all of the classes I wish to provide instances for including the base class interfaces? Or is simply exporting the factory functions enough?

  2. I was also thinking of using smart-pointer features for automatic deallocation, good idea or let the user handle it? I was planning on using the autoptr template which is part of the standard library and available on both platforms right?

  3. Can anyone enlighten on which calling convention I should use? I know its microsoft specific so I hope it doesn't interfere with Linux so should I leave it blank and let it be the default which I think is _thiscall or something along those lines.

  4. I get an error for this piece of code, i'm not sure why but it is due to the extern "C":

The error is: error: declaration of C function ‘std::ostream& operator<<(std::ostream&, const MemInfo&)’ conflicts with| previous declaration ‘std::ostream& operator<<(std::ostream&, const SpeedInfo&)’ here|

error: declaration of C function ‘std::ostream& operator<<(std::ostream&, const analyzed_result&)’ conflicts with previous declaration ‘std::ostream& operator<<(std::ostream&, const MemInfo&)’ here|

... these error messages repeat for all the functions

here is the code:

//WINLIB is my macro for the dllimport/export

extern "C"{

//operator overloading for stream operation
WINLIB std::ostream& operator<<(std::ostream &st, const SpeedInfo &si);
WINLIB std::ostream& operator<<(std::ostream &st, const MemInfo &mi);
WINLIB std::ostream& operator<<(std::ostream &st, const analyzed_result&);
WINLIB std::ostream& operator<<(std::ostream &st, const ustring_set&);
WINLIB std::ostream& operator<<(std::ostream &st, const speed_map&);
WINLIB std::ostream& operator<<(std::ostream &st, const mem_map&);

WINLIB SpeedInfo operator+(SpeedInfo &si, SpeedInfo &si2);
WINLIB SpeedInfo& operator+=(SpeedInfo &si, SpeedInfo &si2);
WINLIB SpeedInfo operator-(SpeedInfo &si, SpeedInfo &si2);
WINLIB SpeedInfo& operator-=(SpeedInfo &si, SpeedInfo &si2);

WINLIB MemInfo operator+(MemInfo &mi, MemInfo &mi2);
WINLIB MemInfo& operator+=(MemInfo &mi, MemInfo &mi2);
WINLIB MemInfo operator-(MemInfo &mi, MemInfo &mi2);
WINLIB MemInfo& operator-=(MemInfo &mi, MemInfo &mi2);
}

All help greatly appreciated.

+1  A: 
  1. Exporting the factory function and including the headers for the classes in user code is sufficient.
  2. If you don't depend on it let the user choose his best tool for the job.
  3. __stdcall
  4. extern "C" gives you a c-style declaration scope - therefore you can't have overloading there. see here. as win32 dll is c-style too you can't directly export overloaded functions (think GetProcAddress()).
Georg Fritzsche
Alrite perfect, i'll be taking of all the dllimport/export from all the classes and will just use it on the factory function.I think i'll also use _stdcall as part of the macro for windows, again last question, shall i put the _stdcall only on the exported factory function or all functions and classes?
iQ
It depends. Pure virtual methods work if you only use basic types, otherwise its needed.A good article with one possible approach to exporting classes can be found [here][1]. [1]: http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx
Georg Fritzsche
Ok, sorry for the mess through missing markup.Try this article: http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx
Georg Fritzsche
yeah great article I've read it partially before. I see the guy only used it on the exported function and used a predefined macro for calling convention. Maybe i should do a ifdef macro check if APIENTRY is defined otherwise make it blank?
iQ
Although APIENTRY is simply defined as __stdcall, i'd use it in the export macro for windows builds if you include windows.h anyway. Otherwise i'd just use __stdcall directly.
Georg Fritzsche
Hmm okay i think i'll use it directly then because I don't have windows.h included in the factory function header file. But only use it for export and not for import?
iQ
The calling convention should be given on import and export.
Georg Fritzsche
+1  A: 

I can't say much about your factory idea (it's > 10 years ago that I did something like this), but regarding #4, your error messages:

If you declare something as extern "C", this means, among some other things, that name mangling is turned off. But name mangling isn't merely a nuisance, it's there for a reason. Name mangling means that the compiler will mangle the names of function argument types into the function names, so that the compiler and the linker can tell overloaded function from each other. If you declare them as extern "C", you're back into C land: The compiler cannot tell overloaded functions from each other and thus overloading doesn't work.

sbi
ahha stupid me I completely forgot about overloadings in C, thank you.
iQ