Any explanation or experience about the way Tuxedo packages it's libraries and how to use them are welcomed.中间件技术社区-Tuxedo论坛
Hi,
Can you post the buildserver command line and the full output from it?
Thanks,
Todd Little
Oracle Tuxedo Chief Architect
Hello,
Hera you go
Makefile content
LIBS=-latmi++ -latmiutl++
SIMPSERV: SIMPSERV.o
CFLAGS="${CFLAGS} $(LIBDIRS) $(LIBDIRS $(LIBDIRS))" \
buildserver \
-s TOUPPER \
-o ${APPDIR}/$@ \
-f SIMPSERV.o
SIMPSERV++: SIMPSERV++.o
CC=xlC_r \
CFLAGS="${CFLAGS} $(LIBDIRS)" \
buildserver \
-s TOUPPER \
-o ${APPDIR}/$@ \
-f SIMPSERV++.o \
-f "$(LIBS)"
Make output
CC=xlC_r CFLAGS="-I /opt/bea/tuxedo9.1/include -I ../include/ -g -DHAVE_CONFIG_H -L ../lib/" buildserver -s TOUPPER -o ../app//SIMPSERV++ -f SIMPSERV++.o -f "-latmi++ -latmiutl++"
ld: 0711-224 WARNING: Duplicate symbol: .tpsvrthrdone
ld: 0711-224 WARNING: Duplicate symbol: .tpsvrthrinit
ld: 0711-224 WARNING: Duplicate symbol: .tpsvrinit
ld: 0711-224 WARNING: Duplicate symbol: .tpsvrdone
ld: 0711-224 WARNING: Duplicate symbol: .userlog
ld: 0711-224 WARNING: Duplicate symbol: userlog
ld: 0711-224 WARNING: Duplicate symbol: tpsvrinit
ld: 0711-224 WARNING: Duplicate symbol: tpsvrdone
ld: 0711-224 WARNING: Duplicate symbol: tpsvrthrinit
ld: 0711-224 WARNING: Duplicate symbol: tpsvrthrdone
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
ld: 0711-317 ERROR: Undefined symbol: .tpinit
ld: 0711-317 ERROR: Undefined symbol: .atmi::Buffer::size()
ld: 0711-317 ERROR: Undefined symbol: .atmi::Buffer::getBuffer()
ld: 0711-317 ERROR: Undefined symbol: .atmi::Buffer::setBuffer(Fbfr32*)
CMDTUX_CAT:1832: ERROR: can't execute xlC_r -brtl -qstaticinline -qrtti=all -I /opt/bea/tuxedo9.1/include -I ../include/ -g -DHAVE_CONFIG_H -L ../lib/ -I$TUXDIR/include -o ../app//SIMPSERV++ BS-37f0a2.c -L${TUXDIR}/lib SIMPSERV++.o -latmi++ -latmiutl++ -brtl -qstaticinline -ltux -lbuft -lfml -lfml32 -lengine -lpthread
make: 1254-004 The error code from the last command is 8.
Stop.
Hereafter the Makefie to build the libraries:
# $Id$
#
# First created by: hkoelman (herbert.koelman@urbix.fr)
#
# Template Makefile.in used to generate Makfile. This is done by running the command
# configure.
#
# Builds library libatmi++.a
BASEDIR=../../
UDATAOBJ=$(BASEDIR)/udataobj/
BINDIR=$(BASEDIR)/bin/
APPDIR=$(BASEDIR)/app/
INCDIR=$(BASEDIR)/include/
LIBDIR=$(BASEDIR)/lib/
# Tuxedo
TUXLIB=$(TUXDIR)/lib
TUXINC=$(TUXDIR)/include
INCDIRS=-I $(TUXDIR)/include -I $(INCDIR)
LIBDIRS=-L $(LIBDIR) -L$(TUXLIB)
LIBS=-latmi++ -ltux -lpthread
CC=cc
CXX=xlC_r
CCC=${CXX}
RANLIB=ranlib
RM=rm -f
DEBUG=-g -bnoquiet
OPTIMIZE=-O5 -qmaxmem=-1 -qsmp
CFLAGS=$(OPTIMIZE) $(INCDIRS) -DHAVE_CONFIG_H
#CFLAGS=$(DEBUG) $(INCDIRS) -DHAVE_CONFIG_H
#CFLAGS=$(INCDIRS) -DHAVE_CONFIG_H
CCFLAGS=$(CFLAGS)
CPPFLAGS=$(CFLAGS)
LDFLAGS=$(LIBDIRS) $(LIBS) -lpthread
TUX_OBJS=Tp.o Queue.o QueueStream.o Tuxedo.o Exception.o AbstractServer.o TuxedoException.o InterruptException.o \
BlockingException.o TimeoutException.o ServiceException.o DiagnosticException.o NomsgException.o \
AbortedException.o
BUFF_OBJS=Buffer.o Field.o BufferException.o
all: libatmi++.a libfml++.a
gencat:
gencat atmi++en_US.cat atmi++en_US.msg
clean:
${RM} *.o core
globber:
$(RM) $(TUX_OBJS) $(BUFF_OBJS) core $(LIBDIR)/libfml++.a $(LIBDIR)/libatmi++.a
libatmi++.a: $(TUX_OBJS) $(INCDIR)/Tuxedo.h $(INCDIR)/Exceptions.h
ar -rv ${LIBDIR}/$@ $(TUX_OBJS)
$(RANLIB) ${LIBDIR}/$@
libfml++.a: $(BUFF_OBJS) $(INCDIR)/Buffers.h $(INCDIR)/Exceptions.h
ar -rv ${LIBDIR}/$@ $(BUFF_OBJS)
$(RANLIB) ${LIBDIR}/$@
Hi,
I'm having a hard time figuring out what you are trying to do. Why are you trying to build libraries that basically are the same as the existing Tuxedo libraries but with some additions, i.e., why are you building libatmi++.a and libfml++.a? Why not just let buildserver include the appropriate Tuxedo libraries and if you have your own libraries build those without including the Tuxedo libraries?
Regards,
Todd Little
Oracle Tuxedo Chief Architect
Hello,
Coding in C++ allows us to write more robust and reliable Tuxedo programs. In addition, the code writing is much smaller then when one uses C.
Exemple :
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "atmi.h" /* TUXEDO Header File */
5
6 int main(int argc, char *argv[])
7 {
8
9 char *sendbuf;
10 long sendlen;
11 int ret;
12
13 /* Attach to System/T as a Client Process */
14 if (tpinit((TPINIT *) NULL) == -1) {
15 (void) fprintf(stderr, "Tpinit failed\n");
16 exit(1);
17 }
18
19 sendlen = 100;
20
21 /* Allocate STRING buffers for the request and the reply */
22 if((sendbuf = (char *) tpalloc("STRING", NULL, sendlen+1)) == NULL) {
23 (void) fprintf(stderr,"Error allocating send buffer\n");
24 tpterm();
25 exit(1);
26 }
27
28 (void) strcpy(sendbuf, "hello");
29
30 /* Request the service TOUPPER, waiting for a reply */
31 ret = tpcall("TOUPPER", (char *)sendbuf, 0, (char **)&sendbuf, &sendlen, (long)0);
32
33 if(ret == -1) {
34 (void) fprintf(stderr, "Can't send request to service TOUPPER\n");
35 (void) fprintf(stderr, "Tperrno = %d\n", tperrno);
36 tpfree(sendbuf);
37 tpterm();
38 exit(1);
39 }
40
41 (void) fprintf(stdout, "Returned string is: %s\n", sendbuf);
42
43 /* Free Buffers & Detach from System/T */
44 tpfree(sendbuf);
45 tpterm();
46 return(0);
47 }
Now here is what you get when you use C++
1 #include <string.h>
2 #include <iostream>
3 #include "atmi++.h"
4
5 using namespace std ;
6
7 int main ( int argc, char **argv ) {
8
9 int ret = -1 ;
10
11 try {
12
13 Tp tp ( "TOUPPER" );
14 char *message ;
15 long len = 100 ;
16
17 tp.init ();
18
19 message = tp.allocate ( "STRING", NULL, len );
20 strcpy ( message , "hello" );
21
22 try {
23 // give it 1 chance with a 1 second delay between retries
24 ret = tp.call ( &message, &len, 1, 1 );
25 cout << "returned string is" << message << endl;
26
27 } catch ( TuxedoException& terr ) {
28 cerr << "Can't send request to TOUPPER." ;
29 cerr << terr.what () << endl ; // detailed error descritpion
30 };
31
32 tp.free ( message );
33 tp.term();
34
35 } catch ( TuxedoException& terr ) {
36 cerr << terr.what () << endl ;
37 };
38
39 return ret ;
40 }
As one can see, the code is shorter and C++ offers a much stronger error handling mechanism. The difference is of course trivial when you consider such a simple program as the one shown here. But as complexity of your code gets greater, the coding effort is significantly reduced using C++.
For exemple when using FML buffersn C++'s strongnbsp&typing helps detecting errors. Casting everything to char * or a void * is not the easiest way to go and in my experience, is error prone.
Here a sample code scrap handling FML buffers.
2 Buffer b;
3
4 TField<long> empid ( EMPID );
5 TField<string> nom ( EMPNAME );
6 TField<char *> carray ( SRVCDAY );
7 nom = "herbert koelman";
8 empid = 2;
9 carray.setCarray("helloworld\0rray", sizeof ("helloworld\0rray"));
10
11 // Added fields
12 b.add ( &empid );
13 b.add ( &nom );
14 b.add ( &carray );
All the handling of type checking and error handling is done in the library code. The object programming paradigm makes this possible.
I used to publish this free library onto Dev2Dev, but it seems that Dev2Dev was discontinued. But if it helps to understand what I'm doing and what's going on, I can send you the source code and documentation.
But all these consideration doesn't explain why the linker is missing the tpinit symbol when I compile my Tuxedo servers
To avoid the problem, I have package a library dedictated to the use of buildclient and one for buildserver.
Edited by: user1086689 on 23 déc. 2011 04:44
Just one more thing that puzzles me. buildserver complains about duplicate symbols and buildclient doesn't ??!! Any explanation ?
If you know how to write proper C code, then there is no issue.
Hi hi, that doesn't help me with my linker issue...