Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Exporting class from a dll with a .def file

Posted on 1998-06-29
12
Medium Priority
?
1,248 Views
Last Modified: 2012-05-04
How to export a C++ non-MFC class from a dll(not a MFC extension dll) with a .def file? Almost all books just tell the readers to use _declspec(). This is really simple. But the VC documentation said that you will have to recompile all .exe files that use the dll if more functions is added to the class! Therefore, I wanted to use a .def file. However, I can find only documentations of exporting functions with a .def file. How to export an entire class? And can I import the class from this dll with _declspec()?

Also, is there any web sites or books that talk about .def files?(I mean talk about some more difficult topics like the question I'm asking)
0
Comment
Question by:sccheung
[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
  • 4
  • 3
  • 3
  • +2
12 Comments
 
LVL 11

Expert Comment

by:mikeblas
ID: 1166889
Using a DEF file will not relieve the requirement to rebuild clients of the DLLs if the class receives more virtual functions, has the existing virtual functions reordered, or gains more member data.

The only way to achieve the late-binding that you're asking for is to use GetProcAddress() on the client side, which is tedious and error-prone at best.

B ekiM

0
 
LVL 22

Expert Comment

by:nietod
ID: 1166890
You can use a .def file just like normal, but the problem is that if the procedures are not declared extern "C", you need to specify the procedures' decorated names.  That is rather ugly.  You are best of just using _declspec(dllexport).  I suspect that is largely the reason it was developed.
0
 
LVL 11

Expert Comment

by:mikeblas
ID: 1166891
Of course, you can't declare the member of a class extern "C" because they must be declared as __thiscall, unless they're static members.

B ekiM



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

 
LVL 2

Expert Comment

by:rayb
ID: 1166892
Have you considered using COM?  This is one of the fundamental operations/purposes of COM.
0
 
LVL 3

Expert Comment

by:danny_pav
ID: 1166893
An alternate version goes like this:
declare wrapper functions for each class member

class MyClass {
  public:
    MyClass();
    ~MyClass();

private:
  ...

public:
  void DoIt();
};

you would then make an .h file like:

#ifdef __cpluplus
extern"C" {
#endif

typedef void * HMYCLASS;

HMYCLASS MyClass_New();
void MyClass_Delete(HMYCLASS h);
void MyClass_DoIt(HMYCLASS h);

#ifdef __cpluplus
}
#endif

I left out the necessary declspec stuff, but you get the idea.
Then each of those wrappers has to call the approprate class member.

0
 
LVL 22

Expert Comment

by:nietod
ID: 1166894
What danny didn't mention was that these interface functions could then be listed in the .def file. as they are extern "C"

However that is lots of work (unless you have a minimual number of functions) and as mike pointed out, it is really for no benefit.  Using a .def file isn't an improvement over the _declspec(dllexport) method unless you need to export at specific ordinals.
0
 
LVL 11

Expert Comment

by:mikeblas
ID: 1166895
Well, the DEF file offers more flexability than just specific ordinals. NONAME, for example, and DATA.

B ekiM


0
 

Author Comment

by:sccheung
ID: 1166896
Comment 1 (Monday, June 29 1998 - 08:18PM PDT):
If I use the GetProcAddress(), I can write a piece of code which reads a text file which contain the name of all of the member functions and use a while loop in that piece of code to get do all GetProcAddress(). That may not be tedious as I can copy all of the member function names from the header file. But the problem is how to use GetProcAddress() in the case of classes and can I still use the _declspec() to export in this case. All the books I've got only tell me how to use GetProcAddress to import an independent function but not member functions of a class. Therefore, I don't know how to deal with the problems that appear when importing member functions. e.g. do I have to import the member variables, do I write GetProcAddress(mydll,"myclass.myfunc") or just GetProcAddress(mydll,"myfunc"), how to declare the functions variables(able to maintain the class structure)?

Oh! My father've just told me to go to bed. I've got to continue replying to other comments tomorrow. Sorry for this delay!
0
 
LVL 22

Expert Comment

by:nietod
ID: 1166897
>> That may not be tedious as I can copy all of the member function names from the header file.
The problem is that the names in the header file aren't the names exported.  Then names get decorated.  They get a bunch of characters appended to the end of them that "discribe" the procedure's parameters.  Those are the names you need.  There are ways of getting them, but I don't think that matters anyways as I will explain next.

You are talking about using GetProcAddress() to get the procedures from the dll.  Why?  If new procedures have been added to the Dll, you don't know what they are for, so you can't call them anyway.  Your program can only work with the procedures that were there at the time the program was written.  Thus you can just use "GetProcAddress() for the specific names you know about at the time the program was compiled, no need to get those names from another source, like a text file.

Finally, the whole reason this issue seems to have come up is that you are worried about handling changes in classes.  However if a class changes, in general you still aren't going to be able to use GetProcAddress() to your advantage, because you can't call a non-static member function with a ordinary function pointer.  (You probably can get around that with some type casting, but that would be dangerious)  Besides the class may have changed size or may have new virtual functions etc.  so the objects created by the EXE could be tottally incompatible with those created by the DLL.  

The only way to make this work safely is two have the DLL create  the objects and return untyped pointers (handles) to them for the EXE to use.  The EXE could manipulate the objects by calling an ordinary (not a member) function in the DLL and specifying the pointer to the object.  

That is not a fun design.  You are better of just recompiling the EXE and the DLL.
0
 

Author Comment

by:sccheung
ID: 1166898
Do you mean I can use ordinary functions to manipulate the class in the EXE? If I changed the class, I just change the implementations of the ordinary functions. That's good. I'm going to use this solution.
0
 

Author Comment

by:sccheung
ID: 1166899
Do you mean I can use ordinary functions to manipulate the class in the EXE? If I changed the class, I just change the implementations of the ordinary functions. That's good. I'm going to use this solution.
0
 
LVL 22

Accepted Solution

by:
nietod earned 200 total points
ID: 1166900
>> Do you mean I can use ordinary functions to manipulate the class in the EXE?

Yes and no.  When the EXE needs to manipulate the class, the EXE calls an ordinary (non-class) function from the DLL and specifies a pointer to object in one of the parameters (first would be typical)  Then the DLL manipulates the object, probably by using a member function.  Note that these functions that the EXE calls (interface functions) will usually use (void *) pointers to point to the object, thus the EXE doesn't actually know what type of object it is pointing to.

Do you understand the implications of the solution?  It means the DLL is object oriented and has all those wonderful OOP advantages.  The EXE or DLL that uses this DLL, will not be object oriented (at least not in the use of these functions).  Thus they don't get the advantages of OOP.  Depending on your needs that may be acceptible.  

Does that work for you?
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
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 viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

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