Link to home
Start Free TrialLog in
Avatar of ulsa
ulsa

asked on

DLL from Visual C++ in Borland C++?

We are using Borland C++. Unfortunately, there is one DLL
created with Microsoft Visual C++ that we have to use and we
can't seem to link it into our application. We don't have the source for it. The DLL is created for use with Visual Basic. I don't know whether this makes it unusable for C++ or not, but we can't find the symbols in it. I have tried creating an import library using IMPLIB, but that library doesn't help. I get "Unresolved external" on each referenced function in the DLL, even though I link in the import library.

When I try to look at the contents of the DLL using the tool
LIB in Microsoft Visual C++ 5.0, it says that the library is
corrupted. However, the DLL works fine with both Visual Basic and PowerBuilder. I think the DLL is created using an earlier version of Visual C++, like 4.x.

I have created a dummy file with stubs of the same functions
as in the DLL and built a dummy DLL using Borland C++ 5.01.
When I use that, it works. When I compare the TDUMP output
for the two DLLs (my dummy and the original), the output
differs significantly. My DLL contains the function names
including the arguments, but the original DLL contains only
the function names. Could the original DLL have been created
using a different calling convention, like PASCAL or something? Does that make it unusable in C++? Shouldn't the arguments be there anyway?

I have also built my dummy DLL using Visual C++ 5.0, but the
resulting import library is not accepted by Borland C++. I
have seen that some people deliver two different import
libraries with their DLLs, one for Visual C++ and one for
Borland C++. The question is if it's possible to create an
acceptable import library without building the DLL in Borland C++, but instead using the existing DLL built by Visual C++.
--
--Ulrik Sandberg, lmiusg@eei.ericsson.se

Avatar of RONSLOW
RONSLOW

There are great differences in calling conventions (and function naming) between Borland and MS.  These are bad enough when using C - but get even worse with C++ (due to name mangling etc).

I assume you do not have the source to this DLL and/or you didn't develop it yourself.

However, if you ARE writing DLL's yourself, I'd suggest you look at using COM because it is a binary standard which addresses all the parameter passing and naming problems that raw DLL's have and is portable across languages.  Don't get confused - COM itself isn't all that complicated - you don't need to write full OLE servers or custom controls - but it is a very nice way of encapsulating functionality within a DLL or EXE and is also nice in that it helps with versioning and allows you to call in-process, out-of-process or remote in exactly the same way.



Avatar of ulsa

ASKER

I didn't develop it myself and I don't have the source.

What I don't understand is why Borland's IMPLIB doesn't find the relevant information for building an import library. Even if the name mangling is different, shouldn't Borland have figured it out by now? It doesn't make sense, because the DLL works for Visual Basic and PowerBuilder.
Avatar of ulsa

ASKER

Adjusted points to 100
You do not mention if you have a header file that was supplied with the DLL or if you created your own. What you have described sounds very much like your C++ code is looking for mangled function names, but the DLL is using the standard Windows naming conventions of just the function name.

If your link errors are looking for a function like "void fna(int)", than you need to add the following to your header file:

extern "C" {
// rest of header file, externs for DLL functions
}

You should also define the functions using the WINAPI type which should be defined in the windows.h file. This should define the funtions to use the pascal naming convention, and avoid the C++ style name mangling.
Avatar of ulsa

ASKER

I used a header file that was delivered with the UNIX version of the library. I'm afraid I can't "define" stuff, since I don't have the source code. Let me rephrase the question somewhat:

a) If a DLL is created "for Visual Basic" (whatever that means), does that make the DLL unusable for a C++ application?

b) Can I trick the linker to find the functions in a DLL "for Visual Basic" by using 'extern "C"'?

c) Could bugs in Borland C++ 5.01 IMPLIB play a part in this problem?
ASKER CERTIFIED SOLUTION
Avatar of y96andha
y96andha

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
In answer to your questions:

a) Generally, such a DLL can be used with any language.

b) using extern "C" and WINAPI in the header file, like I mentioned in my previous post, should be enough to tell your compiler to generate the proper external names for the linker to connect to the DLL, as well as using the correct calling conventions to properly call those functions.

c) I do not think the problem is in the Borland IMPLIB, but in the naming conventions. You need to get Borland C++ to generate the names used by the DLL, and this requires the use of the extern "C" and either the WINAPI type or __pascal type in the extern statement for the functions.

For example, if one of the functions in the DLL is defined as:
int DllFunc1(int x);
you should change the definition in the header to:
extern "C" int WINAPI DllFunc1(int x);

This is what I meant by defining the functions before, that you may need to modify the header file you got in order to make this work.

If you still get an error from the linker saying that DllFunc1 is not found, than you need to either turn off type sensitivity in the link, or use IMPDEF to create a .DEF file form the DLL, modify it, and use IMPLIB to build the proper .LIB file. The modifications to the .DEF file would be as follows:

For each line like this:
   DLLFUNC1 @1
add a line like this:
   DllFunc1=DLLFUNC1

Avatar of ulsa

ASKER

lwiding's first answer wasn't clear enough for me to accept it. However, if I had requested a clarification instead of rejecting his/her answer, I would have given the answer the highest marks. The comment that followed proved to be exactly what was needed, but then another expert was already involved. I apologize for this and blame the turbulent situation I was in, together with the fact that I'm new to this forum.

The other expert's answer was also correct. I managed to solve the problem and I am very grateful for that. I don't see any other solution than to give the points to the second expert.

The correct answer is as follows:
--------------------------------
My header file contained function declarations using the standard UNIX calling convention:

int myFunc(int myArg, char *anotherArg);

All that was needed in order to access the functions in the DLL was the following change:

extern "C" int WINAPI
myFunc(int myArg, char *anotherArg);