Link to home
Create AccountLog in
Avatar of softechnics
softechnics

asked on

unresolved externals linking to gSOAP objects

I've developed a stand-alone Web Service C++ client (WSClient.exe) that works. Now, I need to link the gSOAP generated oject files into a legacy C++ application. So I generate the object files as before, but do not link the objects creating an executable. Instead, I then compile and link my legacy app with the gSOAP generated objects. I get unsatisfied Link errors as follows:

(All in stdsoap2.obj):

_namespaces
___mb_cur_max
plus a couple long std:: fucntions.

I found mb_cur_max and MB_CUR_MAX in stdlib.h and included it, but the error persists. I would think the problem is that my legacy Makefile is not including an object or library that the standalone test client Makefile is including, but I cannot find it. Also, namespaces is not found in stdlib.h, but is found in a few other system includes, but none that are included in the working WS client application.

Any ideas?
Avatar of jkr
jkr
Flag of Germany image

Chances are that you are linking with the wrong version of the CRT (libc.lib vs. msvcrt.lib). What are your compiler and linker options?
Avatar of softechnics
softechnics

ASKER

***********************************************
* The gSOAP makefile (for the legacy system) is as follows (run first - builds the SOAP lib files and my ws client and puts in WebService.lib):
***********************************************

GSOAPDIR=gSOAP
GSOAP=$(GSOAPDIR)\soapcpp2.exe
SOAPH=$(GSOAPDIR)\stdsoap2.h
SOAPC=$(GSOAPDIR)\stdsoap2.c
SOAPCPP=$(GSOAPDIR)\stdsoap2.cpp
WSDL=USMCAccessor.wsdl
WSDL2H=wsdl2h.exe

CC=cl
CPP=cl
COFLAGS=-O2 -c
CWFLAGS=-Wall
CIFLAGS=-I..\include -I..\..\include\stutil32 -I..\.. -I$(GSOAPDIR)
CMFLAGS=-GX
CFLAGS= $(COFLAGS) $(CIFLAGS) $(CMFLAGS)

CPU = i386
PROJ = WebService

#CONSOLE_APP = 1
#GUI_APP     = 1
#DLL_APP     = 1
LIB_APP     = 1

# Define project specific macros
PROJ_OBJS  = $(CPU)\soapClient.obj $(CPU)\soapC.obj $(CPU)\stdsoap2.obj $(CPU)\WSClient.obj

BASE_OBJS  =
OBJDIR     = $(CPU)
EXTRA_LIBS = odbc32.lib odbccp32.lib wsock32.lib
GLOBAL_DEP =
RC_DEP     =
PROJ_DEP   =
INCLUDES   = $(CIFLAGS)
CDEFS      = -DWINNT
lflags     = /INCREMENTAL:NO /PDB:NONE /RELEASE /NOLOGO

!ifdef DEBUG
DEBUG_OPTS = $(ldebug) -debugtype:both
!endif

all:            WSClient $(CPU)\$(PROJ).lib      

# Build rule for WSClient header file (built by gSOAP)
WSClient.h:
                  cd $(GSOAPDIR)
                  $(WSDL2H) -c -o WSClient.h $(WSDL)
                  mv WSClient.h ..
                  cd ..

# Build rule for Web Service Client .OBJ files
WSClient:      WSClient.h WSClient.cpp $(SOAPH) $(SOAPCPP)
                  $(GSOAP) WSClient.h
                  $(CPP) $(CFLAGS) -o WSClient WSClient.cpp soapC.c soapClient.c $(SOAPCPP)
                  mv *.obj $(CPU)

# Build rule for LIB
!ifdef LIB_APP
$(CPU)\$(PROJ).lib: $(PROJ_OBJS)
  lib /OUT:$(CPU)\$(PROJ).lib $(PROJ_OBJS)
  copy $(CPU)\$(PROJ).lib ..\lib
  copy soapH.h ..\include
  copy soapStub.h ..\include
  copy $(GSOAPDIR)\stdsoap2.h ..\include
!endif

clean:
            rm -f *.o soapH.h soapStub.h soapC.cpp soapC.c soapClient.cpp soapClient.c soapServer.cpp soapServer.c soap*Proxy.h
distclean:
            rm -f *.o *.wsdl *.xsd *.xml *.nsmap *.log soapH.h soapStub.h soapC.cpp soapC.c soapClient.cpp soapClient.c soapServer.cpp soapServer.c soap*Proxy.h WSClient

**********************************
* The legacy Makefile is as follows (run second - includes WebService.lib, from above):
**********************************
!include <win32.mak>

PROJ = DBItem

CONSOLE_APP = 1
LIB_APP     = 1

# Default the CPU variable to i386 if not defined.
!ifndef CPU
CPU = i386
!endif

all: $(CPU)\$(PROJ).exe $(CPU)\$(PROJ)Hook.lib


# Define project specific macros
PROJ_OBJS  = $(CPU)\gh_Item.obj
HOOK_OBJS  = $(CPU)\gh_ItemHook.obj

BASE_OBJS  =
OBJDIR     = $(CPU)
EXTRA_LIBS = odbc32.lib odbccp32.lib wsock32.lib netapi32.lib ..\..\lib\DataBase.lib ..\..\lib\remote.lib \
             ..\..\lib\stutil32.lib ..\..\lib\sapi.lib ..\..\lib\sremote.lib \
             ..\..\lib\RapiItemSrv.lib ..\..\lib\CommonBusRule.lib ..\..\lib\DBItemHook.lib \
             ..\..\lib\DBAuthHook.lib ..\lib\WebService.lib
GLOBAL_DEP = ..\include\WSClient2.h ..\include\ItemHook.h ..\..\include\DBItem.h
RC_DEP     =
PROJ_DEP   = ..\..\lib\DataBase.lib ..\..\lib\remote.lib ..\..\lib\sapi.lib ..\..\lib\sremote.lib \
             ..\..\lib\RapiItemSrv.lib ..\..\lib\CommonBusRule.lib \
             ..\..\lib\DBItemHook.lib ..\lib\WebService.lib
INCLUDES   = -I ..\..\include\stutil32 -I ..\include -I ..\..\include -I ..\include\4690
CDEFS      = -DWINNT
lflags     = /INCREMENTAL:NO /PDB:NONE /RELEASE /NOLOGO /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcpmtd.lib /NODEFAULTLIB:libcp.lib

!ifndef NODEBUG
DEBUG_OPTS = $(ldebug) -debugtype:both
!endif


# Inference rule for updating the object files
{.}.cpp{$(OBJDIR)}.obj:
!ifdef DLL_APP
  $(cc) $(cdebug) $(cflags) $(cvarsdll) $(CDEFS) -Zp1 -GX -GF -Fo$* $(INCLUDES) $<
!else
  $(cc) $(cdebug) $(cflags) $(cvarsdll) $(CDEFS) -Zp1 -GX -GF -Fo$* $(INCLUDES) $<
!endif

# Build rule for CONSOLE EXE
!ifdef CONSOLE_APP
$(CPU)\$(PROJ).EXE: $(BASE_OBJS) $(PROJ_OBJS) $(PROJ_DEP) $(PROJ).res
    $(link) $(DEBUG_OPTS) $(conlflags) \
    /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:nafxcw.lib \
    $(BASE_OBJS) $(PROJ_OBJS) $(PROJ).res $(EXTRA_LIBS) \
    -out:$(CPU)\$(PROJ).exe $(MAPFILE)
!endif

# Build rule for LIB
!ifdef LIB_APP
$(CPU)\$(PROJ)Hook.lib: $(HOOK_OBJS)
  lib /OUT:$(CPU)\$(PROJ)Hook.lib $(HOOK_OBJS)
  copy $(CPU)\$(PROJ)Hook.lib ..\lib
!endif

Try to remove '/NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcpmtd.lib /NODEFAULTLIB:libcp.lib' from the 'lflags' in the legacy makefile.
I get several multiply defined errors in msvcrt.lib and libc.lib, then a message from the linker to use the /NODEFAULT option on these files. Then I get only 1 unresolved external on 'namespaces'.
What are the CFLAGS from your Win32.mak?
>>  What are the CFLAGS from your Win32.mak?
I'm using the default Visual Studio Win32.mak file found in the MSVC include folder.

Additional Info:

I linked with the /VERBOSE option and found the mb_cur_max defined in libc.lib, so I only removed the /NODEFAULTLIB option for that file. That took care of that unresolved, but it replaced it with another (ARGHHH!!!). Even with the VERBOSE option, I could not find where 'namespaces' was defined or being used.

The other three unresolved externals are:

WebService.lib(stdsoap2.obj) : error LNK2001: unresolved external symbol "public: static class std::locale::id std::ctype<char>::id" (?id@?$ctype@D@std@@2V0loca
le@2@A)
WebService.lib(stdsoap2.obj) : error LNK2001: unresolved external symbol "private: static int std::locale::id::_Id_cnt" (?_Id_cnt@id@locale@std@@0HA)
WebService.lib(stdsoap2.obj) : error LNK2001: unresolved external symbol "private: static short const * const std::ctype<char>::_Cltab" (?_Cltab@?$ctype@D@std@@0PBFB)
That is related to '/NODEFAULTLIB:libcp.lib' - these functions reside in libcp.lib
I'm pretty sure it is. But if I remove it, then I get several additional errors as a result of multiply defined variables, as follows:

libcp.lib(locale.obj) : error LNK2005: "public: __thiscall std::_Locinfo::_Locinfo(char const *)" (??0_Locinfo@std@@QAE@PBD@Z) already defined in msvcprt.lib(MSVCP60.dll)

libcp.lib(locale.obj) : error LNK2005: "public: __thiscall std::_Locinfo::~_Locinfo(void)" (??1_Locinfo@std@@QAE@XZ) already defined in msvcprt.lib(MSVCP60.dll)

libcp.lib(locale.obj) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char
,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in msvcprt.lib(MSVCP60.dll)

libcp.lib(locale0.obj) : error LNK2005: "public: class std::locale::facet const* __thiscall std::locale::_Getfacet(unsigned int,bool)const " (?_Getfacet@locale
@std@@QBEPBVfacet@12@I_N@Z) already defined in msvcprt.lib(MSVCP60.dll)libcp.lib(locale0.obj) : error LNK2005: "public: bool __thiscall std::locale::_I
scloc(void)const " (?_Iscloc@locale@std@@QBE_NXZ) already defined in msvcprt.lib(MSVCP60.dll)

libcp.lib(locale0.obj) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<cha
r,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined inmsvcprt.lib(MSVCP60.dll)

libcp.lib(wlocale.obj) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<cha
r,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined inmsvcprt.lib(MSVCP60.dll)

libcp.lib(xlocale.obj) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<cha
r,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined inmsvcprt.lib(MSVCP60.dll)

libcp.lib(string.obj) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char
,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in msvcprt.lib(MSVCP60.dll)

libc.lib(crt0dat.obj) : error LNK2005: _exit already defined in msvcrt.lib(MSVCRT.dll)
libc.lib(crt0dat.obj) : error LNK2005: __exit already defined in msvcrt.lib(MSVCRT.dll)
libc.lib(crt0init.obj) : error LNK2005: ___xc_z already defined in msvcrt.lib(cinitexe.obj)
libc.lib(crt0init.obj) : error LNK2005: ___xc_a already defined in msvcrt.lib(cinitexe.obj)
libc.lib(crt0init.obj) : error LNK2005: ___xi_z already defined in msvcrt.lib(cinitexe.obj)
libc.lib(crt0init.obj) : error LNK2005: ___xi_a already defined in msvcrt.lib(cinitexe.obj)

LINK : warning LNK4098: defaultlib "msvcrt.lib" conflicts with use of other libs; use /NODEFAULTLIB:library

LINK : warning LNK4098: defaultlib "libc.lib" conflicts with use of other libs;use /NODEFAULTLIB:library

WebService.lib(stdsoap2.obj) : error LNK2001: unresolved external symbol _namespaces

i386\DBItem.exe : fatal error LNK1120: 1 unresolved externals

Damned if I do, damned if I don't. In this case, three of the four unresolveds go away, only to be replaced by a bunch of multiply defineds.
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
PROGRESS!

I found that if I compile stdsoap2.cpp with -DWITH_NONAMESPACE, this resolves the "unresolved _namespaces" error.
I also must have the /NODEFAULTLIB:libc link flag set to resolve the 'mb_cur_max' undefined error.
I'm down to several multiply defined errors, but I believe they can all be summed up as follows:

libcp.lib(string.obj) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char
,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in msvcprt.lib(MSVCP60.dll)

libc.lib(crt0dat.obj) : error LNK2005: _exit already defined in msvcrt.lib(MSVCRT.dll)

My link command looks like this:

link -debug:full -debugtype:cv -debugtype:both /INCREMENTAL:NO /PDB:NONE /RELEASE /NOLOGO /NODEFAULTLIB:libcpmtd.lib -subsystem:console,4.0  /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:nafxcw.lib   i386\gh_Item.obj DBItem.res odbc32.lib odbccp32.lib wsock32.lib netapi32.lib ..\..\lib\DataBase.lib ..\..\lib\remote.lib  ..\..\lib\stutil32.lib ..\..\lib\sapi.lib ..\..\lib\sremote.lib  ..\..\lib\RapiItemSrv.lib ..\..\lib\CommonBusRule.lib ..\..\lib\DBItemHook.lib  ..\..\lib\DBAuthHook.lib ..\lib\WebService.lib ws2_32.lib  -out:i386\DBItem.exe

What next? ( I knew there was a good reason I deserted the C/C++ ship 10 years ago before getting into Windows programming for a reason. :-) )
EUREKA!

Finally got a good build. The last problem was resolved by placing the -MD flag in the CFLAGS list in my WebService makefile.

I appreciate your patience and assistance in helping me struggle through this quagmire of libraries. Thanks.
Great that you found it. Sorry for not responding earlier, but there's a life without computers also ;o)