Link to home
Start Free TrialLog in
Avatar of danny2
danny2

asked on

link bc++4.5 dll + obj of masm6.11 in VC++4.2

How can i link a borland C++4.5 32 bits dll and object file
made with masm 6.11 in a Microsoft Visual C++ 4.2 project without getting unresolved link errors in object file? The problem is that Microsoft doesn't support good implib.exe  programms which work with VC++4.2 or 5.0. So how can I do it anyway?

futher detailed:

In Borland C++ 4.5 was the 32 bits dll made with declaration like this:

extern "C"
{
      int _stdcall _export Name1(HWND hWnd);
}

and function declaration in the same Borland C++ 4.5
file

int _stdcall _export Name1(HWND hWnd)

{
    // code who also use another 32 bit dll (also orginal borland)
}


The code in MASM 6.11calls Name1 like:

.const
Name1 proto stdcall  HWND:WORD

.data
Hwnd1 word 0

.code
INVOKE Name1,Hwnd1

After compiling in MASM6.11 I  have a object file which should be
linked in MSVC++4.2 or 5.0.

Now I get: filename.obj error LNK2001 a unresolved external symbol _Name1@2


I make my lib file with def headers like this:

library   filename1.dll    //(borland dll)
description 'export function'

exports
       Name1  @1


(MS-dos prompt, using the lib.exe of  MSVC++4.2 : lib  /def:filename.def  /machine:IX86)
(This normally works correct for builded Delphi 2.0/3.0 DLL's)







Avatar of nietod
nietod

Unless all your procedures were declared extern "C" you can't do this anyway.  Borland and Microsoft use different schemes for name decorating so their object code can't be linked together.
Can you provide more details as to what the problem is.  What symbols were unresolved and where were they declared (Borland, Microsoft, or ASM).  Are the symbols, C++ procedures, extern C procedures, C++ objects?
Avatar of danny2

ASKER

Edited text of question
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

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
Note:  If you use the /c option MASM will assemble but not link.  This produces a .obj file that should be passed to the C++ linker.
Avatar of danny2

ASKER

more futher detailed:

To produce my masm object file I use:

ml -c -Zi -coff filename.asm

To link with VC++ I use a .rsp file

link @filename.rsp

filenam.rsp contains:

-entry:DllMain  -incremental:NO -out:filename.xxx -dll
filename.obj
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
advapi32.lib shell32.lib comctl32.lib

special.lib // made with VC++
borland.lib // made with lib.exe (to access borland dll)

/export:_DllMain@12


As you can see I can't use the Borland linker because of the
special.lib.

To nietod : as you see mr. nietod I did already use the way you told me.. but thank for your support anyway!
I can't tell if you have a solution or you are giving up.  It seems like you might be giving up.  If so, I don't think you need to give up yet.  

If you still need help, it seems to me that the problem is not related to the MASM part, but to the fact that you have two libraries (Borland.dll and special.lib) that are produced by different C++ compilers.  What are these libraries?  Is it possible to recompile one of them for the other compiler? (you would have to have the source code for either of them.)  If you don't have source code for the libraries, it may be possible to create a Dll to bridge from one library to the other.  Realistically this could be done only if one of the libraries contained a minimal number of functions that you want to use.  (a few dozen at most).  I could explain how to do this if other options are not available.
Avatar of danny2

ASKER

to mr. nietod:
I need still help and I don't want to give up!
You are right about the fact that I have two libraries
that are produced by different C++ compilers.

Of the special lib (made with VC++) I don't have the source code.
(So I am sticked with VC++)

Of the Borland DLL I do have the source. But in that borland
dll am I using functions of other Borland DLL which of I don't
have the source. With implib.exe I make a lib file so can I use
these functions in my Borland dll.

I did already recompile my Borland DLL for VC++ 4.2 but I get the
same problem again of Link Error Unresolved Symbols with the functions out of that borland DLL (other dll) which of I don't have the source.
That's why I said at the beginning of my question that MSVC++4.2 or 5.0 do not have good tools to make a lib file (implib.exe in Borland C++).

(I do know the names of the functions in the borland dll and with that I make a def file and made a lib file to link it VC++. But I think personally lib.exe is not entirely correct.)    

I do actually know a bit about bridging because I studied the ideas of using Win32 dll in a 16-bit programm or win16 dll in a 32-bit programm. In that case you have to build communication dll's which send messages (API) between them.


I'm not sure if you are aware of this or not, but the problems has nothing to do with implib.  It is simply the fact that borland and Microsoft use different schemes for decorating names.
  If you write a function like

X(int x,char ch)

in you source code it does not appear with the name X to the linker, or to importlib, or to other EXE's or DLL's.  This is because C++ decorates the names (adds on to it) to express information about the parameters, return value, and calling convention.  The procedures might be called something like X@int@char;  The problem is that Borland and Microsoft use different schemes for generating these names.  If you export a fnction from a library produced by Borland it gets exported using a name with there decorating system.  If you import it into a library writen in Microsoft, it takes the simple name you told it to import and determines a decorated name to look for and actually import.  Of course it doesn't find it.

There is a way around this.

Functions declared as "extern c" don't get decorated.  They appear using their simple names.  However, using extern C means that a function can't be overloaded (that is, have more than one version with the same name but different parameters).  That is because name decorating is used to give trully different names to overloaded functions that only appear to have the same name.


How to fix this?  That may depend.  The approach that I'm going to describe will work, but can get tedious if the Borland library is huge (lots of functions) or get messy, if you've got lots of classes.

I'm going to produce a simple example here.

Im goings to say you have a Borland library called B.lib file for which you have no source, but for which the function
X(int,char) is exported and is needed in Visual C.  What you would do is create a DLL in Borland that interfaces between Vissual C and the Borland library.  We'll call the DLL Int.Dll.
What Int.Dll needs to do is to export a function that Visual C can call.  Since Int.Dll is written in Borland, Visual C can't call its functions, unless they are declared extern c.  So Int.dll with need the following function

extern "c" void XInt(int x, char ch)
{
  X(x,ch);
}

that's all there is to the Dll (in this case, you will probably have another function or two, or thousand)

Now you have to use this in visual C.  This could be in an EXE or DLL.  The file needs to know about the extern c function so it would be declared something like

DllImport extern 'c' XInt(int x,char ch);

Then in visual c, you would call XInt, not X and everything will be fine.

There are three sources of problems.  classes (structures), Overloaded functions, and class functions.

Classes and structures:  
you may have problems if class or structure is represented differently by Borland or Microsoft.  i.e. if given the same C++ definition of a class, they might produce different layouts in memory.  This will not happen in simple cases, but COULD happen with derived classes, or classes with virtual functions.  I'don't know if this will be a problem.  Even if it is, it could be gotten around in simple cases.

overloaded functions:
If there is an overlaoded function in B.lib, say X(int) and X(char), you will have to create two non-overloaded functions in Int.Dll, say XIntInt() and XIntChar().  You will have to call the appropriate function in visual C.  If that is a pain, you could create a pair of overloaded functions in visual c that simply call the appropriate interface function, like

X(int i)
{
   XIntInt(i);
};
X(char ch)
{
   XIntChar(ch);
}

then you could just use X() again.

Member functions:
If you have member functions you will have to pass the object (*this) as a parameter.  So given

Cls::Mem(int i)

in B.lib.

you will need

ClsMemInt(Cls *ObjPtr,int i)
{
   ObjPtr->Mem(i);
};

in the interface dll (Int.DLL).

this means you have to call the member function as a regular function in visual c. Instead of

Obj.Mem(1)

you have to use

ClsMemInt(&Obj,i);

If that is too messy, you can declare a class derived from this one in vissual C with no extra members, but that redefines all the member functions.  Each redefined member function just calls the interface function.

Wow.  hope that helps.
Avatar of danny2

ASKER

o.k. thank you so much... Your answer sounds excited, within a few days I will work on it again, and I will let know if it
finally succeeded!