I have built an Ubuntu server 18.04 LTS with gnuCobol 3.1.2 and postgresql installed. I am trying to build an native interface with libpq to communicate with db from COBOL. I have been trying this already several days, but still getting trouble to run the test. First I have compiled the runtime with:
gcc -x -v -o t -lpq -lcob psql_test1.c
This has come back with a list of undefined symbols. I have tried to link the library files directly:
gcc -x -v -o t psql_test1.c /usr/local/lib/libcob.so /usr/lib/x86_64-linux-gnu/libpq.a
The compilation is now correct. It returns 0. But when I run the test with ./t, it comes with error again:
Before connect: 0x0000000000000000
Error: PQconnectdb link problem, try -lpq
I am quite confused, as everything is now compiled correctly and I can find the routine with nm:
$> nm /usr/lib/x86_64-linux-gnu/libpq.a | grep connectdb
0000000000006e00 T PQconnectdb
0000000000006d30 T PQconnectdbParams
Could anybody give me a tip, what should I do to fix this?
Warning: That question seems like a "can of worms", so this answer does not follow any Q+A principles either...
As you compile something and seem to want to include the GnuCOBOL runtime, it would be better to use the GnuCOBOL compile frontend instead of gcc.
gcc -x -v -o t -lpq -lcob psql_test1.c
becomes cobc -x -v -o t -lpq psql_test1.c
.
Your link errors are very likely rooted in either the order of libraries (cobc will reorder them a bit and always include libcob and its path) or in missing library paths.
Try cobc -x -v -o t -L /usr/lib/x86_64-linux-gnu -lpq psql_test1.c
.
But in any case: consider to NOT link agains libpq.a, a static library (you need to relink when you want to update and would need all your postgres calls to be done in the "main" program, because generated so's would have their "own" copy of the library).
but when I run the test with ./t, it comes with error again
Without a sample of the actual code we cannot know, but very likely you do something like CALL 'PQconnectdb' USING ...
, so you have a dynanic call.
For this to succeed you'd have to preload libpq (for example with LD_PRELOAD
or COB_PRE_LOAD
), but with your static libpq that won't work in any case.
or ensure that the symbols from link time stay in, even when they aren't used. To do so add -Q -Wl,--no-as-needed
to your cobc (or gcc) invocation.
What you likely want to do instead: use a static call enabling the linker to directly do the lookup (both for static and shared libraries): Choose one of:
-static
to cobc - but then for all of your COBOL programs that you want to dynamically load you can't use CALL 'prog'
any more and have to use MOVE 'prog' TO program CALL program
instead(calling a variable instead of a literal).-K PQconnectdb
- the list of library functions may get quite long (but no problem when you use a Makefile or similar to do the compilation)CALL STATIC 'PQconnectdb'
... and after all: consider to "stay COBOL" and don't use a native interface but EXEC SQL
, this has the benefit that you don't have to do all the mappings between COBOL variables on your own and "in general" be able to later switch to a different DB later more easy. Example:
ACCEPT DATASRC FROM ENVIRONMENT-VALUE.
ACCEPT DBAUTH FROM ENVIRONMENT-VALUE.
EXEC SQL
CONNECT TO :DATASRC USER :DBAUTH
END-EXEC.
In this case an sql precompiler converts the SQL parts as necessary and translate those to its specific necessary CALLs.
Precompilers known to work with GnuCOBOL and PostgreSQL in general: