Solved

How to export a class through a .LIB

Posted on 2001-07-18
18
371 Views
Last Modified: 2013-12-14
I'm having trouble exporting a class through a LIB file. I have a little Visual C++ project that shall just export a class definition for being linked to other projects.

The test project:

template<typename T>
class __declspec(dllexport) CTest1
{
public:
     T nTestInt;
};

typedef CTest1<int> CIntTest1;

This compiles perfectly, but cannot be exported; neither "CTest1", nor "CIntTest1" is listed by dumpbin.

Other exported structs are listed well.

I may not use MFC, so "AFX_EXT_CLASS" may not be used.

I also tried a .DEF file, e.g. using "EXPORTS CTest1",
but also to no effect (but it might only work for DLLs).
0
Comment
Question by:PC-Alex
  • 10
  • 8
18 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 300 total points
ID: 6293345
The problem is that you are not trying to export a class.  The code abive does not define a class.    it defines a _template_ for a class.  There is a huge difference.   (If you are hungry do you want a meal, or a recipe to make it?  a temlate is a recipe, not a meal.  Its not something tangable, like a class.  It tells the compiler how to make a class, but it isn't itself a class.)

Think of it this way.  That tempalte can be instanciated for 1000s, millions, billions even of different data types.  so if your LIB file had to create instances of the class for each possible data type it would be enourmous  (The lib file can't know ahead of time what classes will be used to instanciate the template, so it would have to do so for all possible types--which is of course impossible.)

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 6293384
Before we get to the solution I also see that you are using __declspec(dllexport) like in

>> __declspec(dllexport) CTest1

This is used to export from a DLL, not a LIB.   Are you creating a DLL or a LIB?  (Note that no matter what, you still can't export a template.)

The usual solution is to provide the template as a source code library.  i.e. you place the template in an include file (.h) and allow any code that needs the template to include it.

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 6293436
If this is for a DLL, then what you can do is to export instances of the template class.  That is, you cna create instances of the template for specific template parameters and export these.  

This makes sense if you know the template will be instanciated for only a few, specific template parameters.  For example, if your template class above is character related in some way, you might only want to instanciate it for only type "char" and "wchar_t".  In that case your library could create instances of the class for these two types and export these two instances.   (Note I've never tried this with a .lib file, so I'm not 100% sure this will work with a .lib file, but it does work with a DLL in VC.)

To do this.  In an include file for the library place the template definition followed by

extern class CTest1<char> ;
extern class CTest1<wchar_t> ;

Then in the source code for the library place

class CTest1<char>;
class CTest1<wchar_t>;
0
 
LVL 22

Expert Comment

by:nietod
ID: 6293460
Actually I think  the source code should contain

template <> class CTest1<char>;
tempalte <> class CTest1<wchar_t>;

instead of

class CTest1<char>;
class CTest1<wchar_t>;

but again, I don't know if this works for .lib files, or just DLLs.   (but in general neither are adequite and the best solution is usually to just provide the template definiition in an include file.)

Let me know if you have any questions.
0
 
LVL 1

Author Comment

by:PC-Alex
ID: 6293690
Hi nietod,

thanks for the info. Using it this way:

class CTest1<int>;

was accepted by the compiler, but also does not appear in that what dumpbin tells me, and seems not to become really exported

It is a good idea to just list all the instances that will be made from the template.

The origin of the problem is this:
 
I have a big DLL, one cpp file, 20 header files. All header files have template definitions.
The cpp becomes compiled to a 10.5 MB OBJ file, and the linker crashes in release mode
(Linking...  .\Debug\CARMABoNet.obj : error : Internal error during ReadSymbolTable).

I have officially opened an issue at microsoft germany, they can reproduce it, but now after 13 days, they still cannot tell me what to do. Their advice was "shrinking the DLL".

So that's what I tried...
0
 
LVL 22

Expert Comment

by:nietod
ID: 6293762
First of all.  Is this for a DLL or a static library (.lib).

>> It is a good idea to just list all the instances that will
>> be made from the template.
It that something you coudl aver know?  In general it is not possible to know this.  i.e. if I create a linked list template class, I can not predict what data types will be stored in the class.   its very unusual when you can predict this, although for some case it might be possible.  Is it possible for your case?

(If its not possible, then you have no choice, you can't export anything and you just palkce the tempalte definiton in your include file and that is te end of it.)

>> The cpp becomes compiled to a 10.5 MB OBJ file,
This probably is the wrong way to solve the problem.

Most likey you need to really pare down the code.  I suspect that its very inneficient. i.e. probably creates many classes and functions that are not needed.  I would try to break the code up into several smaller DLLs.   These will probably come in under the size limit you are encountering and thus will help you avoid the problem.   But that really not the main advantage.  It should help you to organize the code.  You shoudl be able to reate several files, each of what are not dependant on so many include files and so many other classes and functions.  This will reduce coupling and make the project much more managable.  It should also aid you in learning about the depdancies of your design which will help you to make further simplifications to it.  
0
 
LVL 1

Author Comment

by:PC-Alex
ID: 6293919
>First of all.  Is this for a DLL or a static library
>(.lib).

The trouble-maker is a DLL. My goal is to cut slices off that DLL. Whether these are LIBs or DLLs is not the main problem. I tried LIBs, because they become statically linked, and for providing some general purpose classes I think they fit better.

>It that something you coudl aver know?
>In general it is not possible to know this.
The DLL is "legacy", it was not designed by me (in fact it was the consulting service of a very big software company, based near seattle ;-)
There is more "administration" made, instead of further development, so listing the usage is a compromise we can live with (we'd have to change and recompile the lib file if we need another incarnation of a class, thats OK).

Could you explain again the summary of what propose ? I know the necessity of breaking the DLL up functionaly, I'd love to much better understand what all these intertwined class templates do ... but how else can it be done, if these templates are not exported from the subunits ?
0
 
LVL 1

Author Comment

by:PC-Alex
ID: 6293962
>First of all.  Is this for a DLL or a static library
>(.lib).

The trouble-maker is a DLL. My goal is to cut slices off that DLL. Whether these are LIBs or DLLs is not the main problem. I tried LIBs, because they become statically linked, and for providing some general purpose classes I think they fit better.

>It that something you coudl aver know?
>In general it is not possible to know this.
The DLL is "legacy", it was not designed by me (in fact it was the consulting service of a very big software company, based near seattle ;-)
There is more "administration" made, instead of further development, so listing the usage is a compromise we can live with (we'd have to change and recompile the lib file if we need another incarnation of a class, thats OK).

Could you explain again the summary of what propose ? I know the necessity of breaking the DLL up functionaly, I'd love to much better understand what all these intertwined class templates do ... but how else can it be done, if these templates are not exported from the subunits ?
0
 
LVL 1

Author Comment

by:PC-Alex
ID: 6293998
>First of all.  Is this for a DLL or a static library
>(.lib).

The trouble-maker is a DLL. My goal is to cut slices off that DLL. Whether these are LIBs or DLLs is not the main problem. I tried LIBs, because they become statically linked, and for providing some general purpose classes I think they fit better.

>It that something you coudl aver know?
>In general it is not possible to know this.
The DLL is "legacy", it was not designed by me (in fact it was the consulting service of a very big software company, based near seattle ;-)
There is more "administration" made, instead of further development, so listing the usage is a compromise we can live with (we'd have to change and recompile the lib file if we need another incarnation of a class, thats OK).

Could you explain again the summary of what propose ? I know the necessity of breaking the DLL up functionaly, I'd love to much better understand what all these intertwined class templates do ... but how else can it be done, if these templates are not exported from the subunits ?
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 22

Expert Comment

by:nietod
ID: 6294130
>>  My goal is to cut slices off that DLL. Whether these are LIBs or
>> DLLs is not the main problem. I tried LIBs, because they become
>> statically linked, and for providing some general
>> purpose classes I think they fit better.
In terms of organizational improvement, a lib is just as good.  it should help you to discover and improve dependancies.  However, because templates are being used  it may actually result in a larger DLL than the current one.

if you choose to break it up into seperate DLLS, again the total size will probably be larger than the current one, but at each one should be smaller so you don't run into this limit.

Another thing that should help is to take a careful look at what you are exporting.  Don't export things that don't need to be exported.   Exporting in C++ is costly in many ways.  The compiler/linker adds a decorated funciton name to the export table.  such a name might easily be 100 characters and 1/4 k might not be unusual.  If you export a a class with 10 functions each of which have only 100 characters in their decorated name you are looking at 1K in the export table.   That adds up fast.  Pluss exported functions tend to be harder to optimize.

>> Could you explain again the summary of what propose ?
Basically nothing earth-shatteringly novel or helpful.  I'm just suggesting that you clean up the code.  Look for unnecesary classes and functions and delete them.  Simplify the relationships between what remains.  The first step to doing this is going to be breaking that huge source code file into smaller files.  it will help you to see the relationships  between different classes and functions in the code.  It will help you to isolate portions that are not needed.  
0
 
LVL 1

Author Comment

by:PC-Alex
ID: 6294231
I'm still at the same point where I was right from the start.

I want to break up the DLL, but it doesn't work.

I made a new project, and I don't mind if it keeps being a LIB, or if I change it to a DLL.

When trying to export the class definitions, they don't appear in the LIB file (dumpbin tells me so).

I found out one more thing:

When using
"CTest1<int> objInstance;"

then I find exported:
"?objInstance@@3V?$CTest1@H@@A"

but when only using the definitions, like suggested
"template<> class __declspec(dllexport) CTest1<int>;"
or
"class __declspec(dllexport) CTest1<int>;"

nothing is exported.

????



0
 
LVL 22

Expert Comment

by:nietod
ID: 6294415
I would not try exporting the template classes.  Place the template class definitions in the include file and don't try to export specific instanciations of them.  This might make the code larger, but it actually can make it smaller too.  (if you export a template class, the compiler is forced to create ever single function of that class.  If you don't export it, but just use it as needed, then the compiler creates only the functions you use. So this might be smaller, howeve it coudl be larger at times since it may end up creating multiple copies of these functions.)  it certainly makes it simpler.
0
 
LVL 1

Author Comment

by:PC-Alex
ID: 6294564
nietod,

I see what you mean, but this would lead to the fact that the DLL can't be broken up, as I already explained: There are 20 Header files with all kind of templates, each dependant on another, and one cpp file with only some include - statements, plus a DllMain(), plus some constants - nothing more.

This would mean I cannot break up the module.
0
 
LVL 22

Expert Comment

by:nietod
ID: 6295744
Why does that mean you can't break it up?

To me it says "you must break it up"  It sounds very poorly organized.  (Obviosuly I haven't seen the code, but it certain sounds likely.)
0
 
LVL 22

Expert Comment

by:nietod
ID: 6295768
What types of things does the DLL do?
0
 
LVL 1

Author Comment

by:PC-Alex
ID: 6295921
>Why does that mean you can't break it up?

How should I do it ? What shall I separate ? You said yourself that the header files cannot be separated, because they are heavily template based, and cannot export their stuff.

So what can then be broken up ? The cpp file which consists of some include directive and a DllMain function ?

>What types of things does the DLL do?

It is a so called "Business object net", lots of classes intertwined in one another. It shall make it easy to define a business object with some very few macros.

It provides basic stuff for each of these classes, defined under the hood: You can call a funtion for having the class persisted in an XML string, or for filling the whole state(s) with a single XML. It automatically offers "set" and "get" functionality for each data field, has provisions for list and map objects, and of course has all things of conversions of data types included.
0
 
LVL 22

Expert Comment

by:nietod
ID: 6296422
>> You said yourself that the header files cannot be separated,
>> because they are heavily template based, and cannot export their stuff.
That doesn't mean they can't be broken up.

Unfortunately, without nowing more--probably a lot more--about the code I can't talk very intellignetly about it.   I give you soem ideas of some types of things that you might do.  This is entirely hypothetical, none of it might apply to your actual case.

You mention containers(list and map objects)  This sound like very high-level constructs.  They probalby use the bisines object classes in their impilmetation  (presumably they have to store objects derived from some sort of base bissiness object class.)  So they rely on much of the rest of the code, however it is unlikely that that much of the rest of the code relies on them.  And any code that does relly on them code is probalby very high-level in nature too.  So these can probalby be broken out into an independant library (DLL, LIB, include file depending on factors I can't evaluate)  Very few other files in the entire project will then depend on this file.  And hopefully this file will depend on only a limited number of other files in the project.  That is an improvement in organization.  

This is one type of organizational imrovement. breaking out portions that tend to be loosly coupled from other potuions.

Here is another type.

On the other side of things, you have features for object permenance.  While the base class needs to define object permenance in its interface (have procedures for reading and writtin the class to XML), the code for those procedures don't need to appear in the interface or throughout the project.  Ostlikely you can ceate seperate .cpp file that impliments the object permenance code.  This file will be compiled and linked into the library (DLL or LIB) that defines the base class.  But it can be kept distinct from much of the rest of the code for compilation purposes.  This is a different type of improvement.  Since virtually everything will depend on this bussiness object base class, virtuall everything depnds on the object permanance code, but that doesn't mean it needs to depend on the implimentaiton of that code.  if that code has procedures for tranlation ASCII to XML  or something like that, those procedures don't need to be "seen" by most of the rest of the program.  if that code has an XML formatter class, that class doesn't need to be seen by the rest of the program.  So by breaking the code in this way, the remainder of the program is clearly not depedant on certain portions of the code, and is thus that much simpler, both to understand, and to compile.

You might consider reading "Large Scale Program Design" by Lakos.  Its probably the only book on this subject.  I'm actually not thrilled with the book, but its almost certainly the best on the subject.  it would probalby help some.
0
 
LVL 1

Author Comment

by:PC-Alex
ID: 6314417
nietod,

thank you for your patience.

Although this all didn't lead me to a solution, you tought me that realizing my idea isn't possible.

You deserve some excellent points.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
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 be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

758 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

12 Experts available now in Live!

Get 1:1 Help Now