Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Templates with DLLs (VC++)

130 views
Skip to first unread message

Les Matheson

unread,
Jan 2, 1997, 3:00:00 AM1/2/97
to

Charles,
I've never had this problem, despite using template members in exported
classes for
a long time. -- in fact, I compiled your example with no problem. Suspect
some problem
with compiler options related to templates, but first, have you seen this
note from books online?...
PSS ID Number: Q134980
Article last modified on 10-12-1995

2.00 2.10 2.20

WINDOWS NT

---------------------------------------------------------------------
The information in this article applies to:

- The Microsoft Foundation Classes (MFC) included with:
Microsoft Visual C++, 32-bit Edition, versions 2.0, 2.1, 2.2
---------------------------------------------------------------------

SYMPTOMS
========

The Compiler issues the following warning for a class derived from one of
the MFC classes:

warning C4275: non dll-interface class <XXX> used as base for
dll-interface class <YYY>

A related warning is issued when an object of some MFC class is embedded as
a data member of a user-defined class:

warning C4251: <identifier> : class <XXX> needs to have dll-interface
to be used by clients of class <YYY>

See the "Sample Code" section of this article an example of a class
declaration that generates these warnings.

CAUSE
=====

The DLL version of MFC does not export its classes by declaring them with
"class __declspec(dllexport)." Instead, it exports its classes through
entries in the EXPORTS section of its module definition (.def) file.

Because the compiler has only the header files to work with, it cannot
determine whether the MFC classes were actually exported, and therefore it
issues the warning.

RESOLUTION
==========

Because the MFC classes are in fact exported, these warnings can be safely
ignored. As shown in the DLLHUSK sample, you can disable these warnings by
using the following pragma statements:

#pragma warning(disable: 4275)
#pragma warning(disable: 4251)

On the other hand, if the warnings refer to some user-defined class rather
an MFC class, you should ensure that the class is exported before disabling
these warnings.

STATUS
======

This behavior is by design.

MORE INFORMATION
================

Sample Code to Reproduce Behavior
---------------------------------

/* Compile options needed: None
*/

// The following class declaration causes a C4275 warning
// because the CObject class is not also declared with
// __declspec(dllexport).

class __declspec(dllexport) CMyClass : public CObject
{
...
// The following data member causes a C4251 warning,
// because the CString class is not declared with
// __declspec(dllexport).

CString m_strName;
...
};

REFERENCES
==========

For more information, please see MFC TechNote 33 for a discussion of the
reasons behind the decision to export MFC's classes in the module
definition file rather than in the class declaration.

Additional reference words: 2.00 2.10 2.20 3.00 3.10 3.20
KBCategory: kbprg kberrmsg kbprb
KBSubcategory: MfcDLL
============================================================================
=
Copyright Microsoft Corporation 1995.

Charles Calkins <calk...@arch.wustl.edu> wrote in article
<01bbf8f5$d22b0010$d481fc80@ricky>...
> Greetings
>
> I'm writing a DLL in which an exportable class has a member variable
> which is an instantiation of a template, for instance:
>
> template <class T>
> class A {
> T t;
> public:
> A() {}
> };
>
> class __declspec(dllexport) B {
> A<int> a; // warning here
> public:
> B() {}
> };
>
> When I compile the DLL with Visual C++ 4.2, it generates the warning:
>
> warning C4251: 'a' : class 'A<int>' needs to have dll-interface to be
> used by clients of class 'B'
>
> The minimal documentation on C4251 implies that the template itself would
> need to be exported, but how does one export a template? I wouldn't
expect
> it to work, but trying:
>
> class __declspec(dllexport) A {
>
> generates
>
> error C2960: template 'class' requires a tag-name
>
> I also considered trying to export a forced instantiation of the
> template, but adding
>
> template __declspec(dllexport) A<int>;
>
> compiles, but the still warning C4251 is generated.
>
> Any thoughts? I'd prefer not to ignore the warning and hope for the
best,
> but at present I don't have an obvious way around it.
>
> Thanks
>
> Charles Calkins
> calk...@arch.wustl.edu
>

Charles Calkins

unread,
Jan 2, 1997, 3:00:00 AM1/2/97
to

Ken Hagan

unread,
Jan 13, 1997, 3:00:00 AM1/13/97
to

To export class Foo, either you or the compiler must export function
entry points in the DLL for all the member functions of Foo. If you use
__declspec(dllexport) for ordinary classes the compiler does this for
you. Failing that, you can include /EXPORT options in your linker
command line for all the mangled names. As applied to templates, you
couldn't expect the compiler to issue export definitions for all
possible instantiations, since there is an infinite number of them!
Therefore, each one must be exported separately.

In your case, I can think of three approaches. You could...

1 Use the explicit instantiation syntax and export the class at
that point. For example...
template __declspec(dllexport) class A<int>;
..passes the compiler syntax check without any complaints. I suggest
(to the world in general) that this is the natural method that ought to
work. Sadly, it doesn't seem to export anything. You could submit a
"bug" report through http://www.microsoft.com/Support/Email/C++.

2 Ignore the problem completely. You have made "a" a private
member so clients of the DLL will never need to call the member
functions of A<int> directly unless you declare friend classes of B. I
suggest this is the approach you take in your code.

3 Write /EXPORT options for all the mangled names of A<int> and
ignore/suppress the compiler warning. Mangled names for templates are
only slightly more tortuous than those for conventional classes. This
method will certainly work but requires some effort for each new
exported instantiation. I suggest that this is a workaround where method
2 is insufficient.
--
Ken Hagan


0 new messages