[comp.windows.ms.programmer] DLL's, _export and C++ classes in BC++

cadsi@ccad.uiowa.edu (CADSI) (05/14/91)

OK, I have RTFM'ed (multiple times) BC++ and the MS-SDK (don't ask me
why as it doesn't know C++).  Has ANYONE successfully _export'ed
a class from a DLL?  I _export the thing in my DLL, declare it as
huge in the regular Windows code.  Then I create an object of
that class in the Windows WinMain function.  No matter what I do,
tlink always says the methods of the _export'ed class are undefined
externals.  Yes, I added the dll.lib to my link command line.  Anybody?

|----------------------------------------------------------------------------|
|Tom Hite					|  The views expressed by me |
|Manager, Product development			|  are mine, not necessarily |
|CADSI (Computer Aided Design Software Inc.	|  the views of CADSI.       |
|----------------------------------------------------------------------------|

David_Dave_Tamashiro@cup.portal.com (05/16/91)

This might be a dumb answer, but did you look at the dlldemo.exe that
is included with BC++?   Maybe that will have your answer.


Dave

cadsi@ccad.uiowa.edu (CADSI) (05/17/91)

From article <42360@cup.portal.com>, by David_Dave_Tamashiro@cup.portal.com:
> This might be a dumb answer, but did you look at the dlldemo.exe that
> is included with BC++?   Maybe that will have your answer.
> 
> 
> Dave

Yes I had.  BUT, I think I solved it.  I forgot to put the _export
keyword on the actual methods in the source files.  I did put the _export
on the class for the DLL and huge for outsiders.  BUT, like a dope, I
neglected the actual method:

	_HashINT32 HashTable::lookup(...)

is really supposed to be:

	_HashINT32 _export HashTable::lookup(...)

Now, Mr. Borland out there, the linker was not exactly helpfull since it
only reported that

	unsigned long HashTable::lookup(unsigned long)

was undefined (I have _HashINT32 typedefs), not

	unsigned long _export HashTable::lookup(unsigned long)

I know how it is though, but think on it.

|----------------------------------------------------------------------------|
|Tom Hite					|  The views expressed by me |
|Manager, Product development			|  are mine, not necessarily |
|CADSI (Computer Aided Design Software Inc.	|  the views of CADSI.       |
|----------------------------------------------------------------------------|

David_Dave_Tamashiro@cup.portal.com (05/18/91)

I found a fix to this problem.  Set you linker to ignore Upper/Lower
case.  I know this is not an ideal solution but it seems to work.


Hope this helps,

Dave

David_Dave_Tamashiro@cup.portal.com (05/18/91)

Tom,
I am glad you fixed your problem.  Turns out I am working on a different
bug/feature??

It seems that when I compile C (not C++) DLL functions, I have to use
the PASCAL calling convention or else the linker will not find my DLL's
in my *.lib file.    I can get around this problem by setting the linker
to ignore upper/lower case; the code seems to work in any case.

I have a question regarding the use of the huge and _export keyword:
When I  compile C DLL's, do I still have to declare my DLL's 
as "huge" in my main application code?  I have succesfuly compiled my
main program(and linked it) using header files which alternatively
declared my DLL's as "huge" and "_export".  Is the linker going to do
something strange if it see's the "_export" function prototype in both
the DLL *.c file and the main app *.c file?

Also, does anyone know why Borland decided to use the huge keyword when
defining DLL classes?  Whats wrong with the good ole FAR keyword.  Does
their huge keyword still mean normalized far pointers (i.e. 1Mbit pointers)
or does it really mean their  pointers can access 2^32 memory locations?
  ...And... if it does, who cares??? 

Thanks,
Dave

cadsi@ccad.uiowa.edu (CADSI) (05/19/91)

From article <42434@cup.portal.com>, by David_Dave_Tamashiro@cup.portal.com:
> I found a fix to this problem.  Set you linker to ignore Upper/Lower
> case.  I know this is not an ideal solution but it seems to work.
> 
> 

DA__IT!  I thought I had the fix.  I forgot to use the _export keyword
on my methods.  I had it only on the class.  BUT, still no help.  I will
have to try the idea above.  I still don't get it.  Borland's dlldemo
does JUST what I am trying to do.  Matter of fact, i just copied their
_EXPORT macro idea.  STILL, NO FIX!  I hope your right.  Maybe we should
take this to e-mail because I don't want to waste bandwidth with shots
in the dark.  I'll post the fix when I find it so noone else will
have to deal with this idiotic problem.

|----------------------------------------------------------------------------|
|Tom Hite					|  The views expressed by me |
|Manager, Product development			|  are mine, not necessarily |
|CADSI (Computer Aided Design Software Inc.	|  the views of CADSI.       |
|----------------------------------------------------------------------------|

ejs@borland.com (Eric Swenson) (05/29/91)

In article <42447@cup.portal.com> David_Dave_Tamashiro@cup.portal.com writes:
>
>It seems that when I compile C (not C++) DLL functions, I have to use
>the PASCAL calling convention or else the linker will not find my DLL's
>in my *.lib file.    I can get around this problem by setting the linker
>to ignore upper/lower case; the code seems to work in any case.

Well, you don't really have to use the PASCAL calling convention.
However, the PASCAL calling convention has the side effect of
uppercasing your symbol names.  You are running into a
case-sensitivity problem (as you no doubt realized).  There are two
switches to govern the various combinations.  TLINK's /c switch
governs whether TLINK will *force to upper case* symbols read in from
PUBDEF, EXTDEF, and COMDEF records -- it /c is set, it won't do this.
TLINK's /C switch governs whether TLINK will *force to upper case*
symbols read in from IMPDEF (import definition) and EXPDEF (export
definition) records, or from symbols in the IMPORTS or EXPORTS section
of the module definition file.  The default, /C-, is to force all
these symbols to UPPERCASE.  So if you use /c /C- (BCC's defaults),
you will run into case-sensitivity problems because your symbols are
in mixed case in the EXE (PUBDEFs, EXTDEFs, and COMDEFs) and the
symbols are in uppercase in the imports and exports.  Thus, there
isn't a match.  If you use /C (to force imports and exports to be case
sensitive), your problem will go away.

Note this weirdness is due to TLINK's notion of case-sensitivity.  As
mentioned above, TLINK forces to uppercase all symbols when treated
case insensitively.  In the TLINK source code, the /c and /C switches
are called "uppercase flags" rather that "case-sensitive" flags.

>I have a question regarding the use of the huge and _export keyword:
>When I  compile C DLL's, do I still have to declare my DLL's 
>as "huge" in my main application code?  I have succesfuly compiled my
>main program(and linked it) using header files which alternatively
>declared my DLL's as "huge" and "_export".  Is the linker going to do
>something strange if it see's the "_export" function prototype in both
>the DLL *.c file and the main app *.c file?

Yes, you need to use "huge" in your EXE and "_export" in your DLLs.
_export implies huge, but has the additional effect of exporting the
member functions (probably only public and protected ones, but I'm not
sure).  What we do here (at Borland) is to define a macro __CLSTYPE__ 
which when compiling for a DLL expands to "_export" and when compiling
for an EXE expands to "huge."  

The reason you need "huge" in the EXE is to force the compiler to
assume far vtable and far this pointers.  This is what the code in the
DLL will be expecting.

>Also, does anyone know why Borland decided to use the huge keyword when
>defining DLL classes?  Whats wrong with the good ole FAR keyword.

I wasn't involved in this design decision, so please don't flame at
me, but... "far" means that the class will be allocated far and thus,
the this pointer is forced to be far.  "huge" means "far", but
additionally, the vtable pointer is forced far.  

>Does
>their huge keyword still mean normalized far pointers (i.e. 1Mbit pointers)
>or does it really mean their  pointers can access 2^32 memory locations?
>  ...And... if it does, who cares??? 

No, huge just means that the vtable pointer and this pointer are 16:16
pointers (far) rather than near.  Note than in the far data models
(compact and large), this will be the case anyway.

-- Eric Swenson (ejs@borland.com)