__declspec( dllexport ) with template

I write a program that contains class and struct , the class
is a template class , when I export my class and struct
as dllexports , I get an warning that I can't shake , the warning go away if I declare T* t as public data , this
is the code and the explanation , the warning is shown as comment

#include <windows.h>

template <class __declspec( dllexport )       T> class __declspec( dllexport )      CClass
{
      protected :

            T*      __declspec( dllexport )            t;      // when this is declared as public data , there is no problem      

      public :

            int                  p;
};


struct __declspec( dllexport ) s1
{
      int                  a;
      int                  b;
};

struct __declspec( dllexport ) s2
{
      int                  a;
      int                  b;
      CClass<s1>      c; // this yields warning : class 'CClass<struct s1>' needs to have dll-interface to be used by clients of struct 's2'
};

class __declspec( dllexport ) s3
{
      public :

            int            a;
                        s3();
                        ~s3();
            void      go();
};



int PASCAL WinMain(  HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszCmdLine,
                     int nCmdShow)
{


      return TRUE;

}
LVL 1
moshemAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

nietodCommented:
I have never seen "__declspec(dllexport" used the way you are using it.  Either you know something I don't or that might be your problem.

I've seen it used when declaring a class like

class __declspec( dllexport ) s1
{
   int a;
};

but I've never seen is for a member declaration like

CClass
{
    T* __declspec( dllexport ) t;
};

also I've never seen it in a template declaration in either of the uses you have, like

template <class __declspec( dllexport ) T>
class __declspec(dllexport ) CClass
{
};

Besides how can a template class be DLL exportable?  The DLL could export the template only for specific types.  It can't export it for all types, it does not "know" what types will be needed by EXE's and other DLL's that use it.
0
moshemAuthor Commented:
those wierd things you mentioned are testing I did to elimanate any forgoten declaration , in any case I can't bring this
code to compile without an dll export warning, I don't need the
template to be expotable but the class created via the template
can you help ?
0
nietodCommented:
No.  Template classes can't be exportable.  How could they be?  The DLL can't know at compile time what it will be linked to at run-time.  The EXE's and DLL's it is linked to could use the template class for classes that the DLL did not instantiate the template for.

For example say you write a swap template function that switches two of something i.e.

template<class T>
swap(T a,T b)
{
 T c = a;

 a = b;
 b = c;
};

The DLL could provide exports of the swap function for different types, like int, char, double.  But it could not provide exports for ALL types.  An EXE might try

class myclass
{
};

myclass A;
myclass B;

swap(A,B);

How could the DLL know at compile time that this version of swap would be needed at run-time?  It is theoretically possible to create code to impliment the procedure for any type (it would be pretty easy in this case) but I doubt any implimentation does so because it would be extremely hard to do.

However, a template can be instantiated for a class that is exportable, like

****in DLL****
__declspec(dllexport) class ExpCls
{
   ExpCls();
};
ExpCls::ExpCls()
{
   // do stuff. //
};

template<class T>class TmpCls
{
   T a;
};

***** in EXE *****
TmpCls<ExpCls> A;

Whenever the template manipulates ExpCls it will use the DLL's code.  Thus when A is constructed, the ExpCls constructor in the DLL will be called.  However, the code for calling the constructor will be in the EXE.  Any code or logic that is placed in the template will appear in the EXE (podsibly many times)  however, that code will call the DLL for manipulating the ExpCls member of the template class.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

moshemAuthor Commented:
I did not mean that the template class itself will be exportable , but the Instance of it relative to a specific data type whould be , the extra dllexport statments are just for experimenting to find out what the problem is , so what am I doing wrong

BTW

thanks for taking the time to write a long a good answer!
0
nietodCommented:
It would be possible for a DLL to export procedures for instances of template classes of specific types.  If an EXE needed additional types it would have generate the code instead of using the DLL.  However, I don't think that MS Vissual C++ currently does that.  I think it just does not export templates.  (Although I could be wrong and this could be tested.)

However, you can (probably) get around this using derived classes.  For example, if you have a dynamic array template class, you could export dynamic character and dynamic integer arrays as follows.  (I think)

template <class T>
class DynAry
{
  // stuff.
};

__declspec(dllexport) class IntAry : public DynAry<int>
{
};

__declspec(dllexport) class ChrAry : public DynAry<char>
{
};

0
moshemAuthor Commented:
Yes , you see that was my original question , what you just
suggested was exactly what I did in the first place ( see my
original question) the instance of the template class is'nt
exportable ( the stuff with derived class can't be right , it's
too akward , besides what's the diffrence?!) let me know what
you think
0
nietodCommented:
I tried it.  The technique I suggested above worked, although there might have been some syntax errors.  Here is the code I just tried.

*****************************

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#define DllImp __declspec(dllimport)
#define DllExp __declspec(dllexport)

template <class T>
class DllExp TmpCls
{
  T Itm;
  TmpCls(T *Ini);
};

template <class T>
TmpCls<T>::TmpCls(T *Ini)
{
  Itm = Ini;
}

class DllExp IntCls : public TmpCls<int>
{
};

class DllExp ChrCls : public TmpCls<char>
{
};

********************************

I created a DLL using this and looked at the exports with DUMPBIN (a tool provided with vissual C++).  It exported two procedures, the constructor for IntCls and the constructor for ChrCls.

The only problem is that it generated a warning that the bass class in the declared dllexport.  The warning apparently can be ignored.  (You can get rid of the warning with a pragma dirrective.)

I'm having trouble understanding you last comment.  If this doesn't help you, ask again, a little more clearly, if possible.


0
nietodCommented:
another thing.  If this isn't what you need.  You should reject my answer so that other people can help you.  Usually other experts will put helpfull comments in locked questions, but for some reason they have not in this case.  Unlocking the question might get some more responses.  
0
moshemAuthor Commented:
The warning *IS* my problem , that is what I wanted to resolve in the first place , the code compiled but that warning puzzeled me... if you say this can be ovecome using pargma , then tell me how! anyway did you try to access that dll and create an instance of that class with no problems ?
0
nietodCommented:
Are you sure the warning is your only problem?  I suspect that your original code did not cause the DLL to export instances of the template and I even if it did is suspect that the exe would not import instances of it.  I could be wrong, however.

Anyway, getting rid of a warning is easy.  Use
#pragma warning(disable: ####)
where #### is the warning number (the digits only) that you want to disable.  (I don't remember the number of this particular warning.)

If you don't want to dissable the warning everywhere in your code you can turn the warning back on at the end of the code that produced the warning you want to ignore.  To turn the warning back on use:
#pragma warning(default: ####)

However, the current version of Vissual C++ 5.0 doesn't handle this perfectly.  Some of the pragma warnings I have in place work perfectly all the time.  Some of them work part of the time.  That is, on some compiles they produce no error and on some they do.  I suspect the problem has to do with the use of precompiled headers and incremental compilation.  Its like the compiler is missing the pragmas when it doesn't compile a portion of the code and this causes the warnings in the portion of code that follows.
0
moshemAuthor Commented:
before we finish this discussion , can you tell me if you succeeded in creating a dll and ignoring warnings by using
the pargma , and then use it from another exe (create instance of a class or derive from it) ?
0
nietodCommented:
I didn't test that far.  I created the dll and SAW that it had the exports listed I did NOT test that an EXE would use the exports in the DLL rather than creating the code in the EXE  But I doubt this is a problem.  

If you can't test if an EXE is using your DLL's procedures (rather than creating its own) let me know and I'll see If I can test it in a day or two.

I did not try to ignore the warnings.  Besides, the outcome of my test in this would be irrelevant to you.  You could get different results.  (From compile to compile even.)  However, this is pretty much a bug and will probably be fixed in the future.  I've been told it may be fixed in service pack 3 which was released a couple weeks ago.  I'm waiting on a copy.

0
moshemAuthor Commented:
Thanks for an excellent discussion
0
nietodCommented:
Is it working okay for you then?  
0
moshemAuthor Commented:
I did not have time for that , but Iwill check , anyway , your help
was great , so I decieded to give you the points
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.