bug-gnucobol
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [open-cobol-list] cobc linkage bug on Mint Linux ?


From: Michael Anderson
Subject: Re: [open-cobol-list] cobc linkage bug on Mint Linux ?
Date: Thu, 18 Jul 2013 04:06:26 -0500
User-agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130623 Thunderbird/17.0.7

On 07/17/2013 09:28 PM, Patrick wrote:
Does anyone have a fairly new install of Mint 15 to double check my 
findings? Can anyone run this on Ubuntu to see if it's introduced upstream?
On Ubuntu 12.04, it compiled fine, but I'm running Python 2.7

$ cobc -x cobpy.cob -lpython2.7
$ ./cobpy
link cobpy with -lpython2.6
libcob: Cannot find module 'Py_Finalize'

So I commented-out the call to Py_Finalize...

$ cobc -x cobpy.cob -lpython2.7
$ ./cobpy
link cobpy with -lpython2.6
$

So, it seems like 'Py_Initialize' was found by the coblib runtime?, but a Call exception occurred and then Py_Finalize is not found.
$ ldd cobpy
    linux-gate.so.1 =>  (0xb7773000)
    libcob.so.1 => /usr/local/lib/libcob.so.1 (0xb7721000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7578000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb754b000)
    libgmp.so.10 => /usr/lib/i386-linux-gnu/libgmp.so.10 (0xb74cc000)
    libncurses.so.5 => /lib/i386-linux-gnu/libncurses.so.5 (0xb74aa000)
    libtinfo.so.5 => /lib/i386-linux-gnu/libtinfo.so.5 (0xb748b000)
    libdb-5.1.so => /usr/lib/i386-linux-gnu/libdb-5.1.so (0xb7303000)
    libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb72fd000)
    /lib/ld-linux.so.2 (0xb7774000)
    libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb72e2000)


Maybe I'm doing something wrong. I've only been developing software in the Unix env since 2008.
Prior to 2008, MPE/iX was my OS of choice.

So whats going on, look at readelf.......
$ readelf -a /usr/lib/libpython2.7.so|grep Py_Initialize

   941: 000a4cc0  2615 FUNC    GLOBAL DEFAULT   11 Py_InitializeEx
  1517: 000a5700    32 FUNC    GLOBAL DEFAULT   11 Py_Initialize

$ readelf -a /usr/lib/libpython2.7.so|grep Py_Finalize

  1267: 00069750   600 FUNC    GLOBAL DEFAULT   11 Py_Finalize

So Py_Finalize is in their, what the heck? I don't know, there maybe a bug in the OC "CALL" statement, but for me, there is always a work around.

Lets try it in C.

$ more gccpy.c
#include <Python.h>

int
main(int argc, char *argv[])
{
  Py_Initialize();
  PyRun_SimpleString("from time import time,ctime\n"
                     "print 'Today is',ctime(time())\n");
  Py_Finalize();
  return 0;
}

$ cobc -x -I/usr/include/python2.7 gccpy.c -lpython2.7
$ ./gccpy
Today is Wed Jul 18 02:40:35 2013
$

It works! and notice I used cobc to compile it!
I've had similar issues with Tcl... and I've done lots of Cobol/Tcl running in production environments since 2008.

The purpose behind embedded scripts, Python, Tcl, Guile, or similar, is for me, portability, not being tied to specific compiler features.
Or to modify key features of your software without recompiling.... just change your scripts. there are pros an cons.

Maybe a work-around, but I get better (more reliable) results using my own (Cobol Friendly) C wrapper library to call the C functions that were not originally designed to be called from Cobol, not calling these directly from Cobol, but instead called from a library that was designed to be called by Cobol.
That said, dynamic linking should work correctly.

Maybe a bug in coblib, and if so, even if it gets fixed I'll still prefer using a dynamic wrapper library to do these types of things.

Example:
This may help with embedded Python also.

in C:

extern void TCLEVAL (Tcl_Interp **tclhandle, char *script, int *result)
{

    *result = Tcl_Eval(*tclhandle, script);
}

Then in Cobol:
     Move low-values To TCL-BUFFER.
     String "some Tcl statement" delimited by size into TCL-BUFFER.
     CALL "TCLEVAL" USING TCL-INTR TCL-BUFFER TCL-RESULT.


BTW: jim looks like a nice minimal Tcl library, which is a good thing for packaging your software.
However, in development mode on Ubuntu, I just use the standard Tcllib that comes with Ubuntu.
"sudo apt-get install tcl8.5-dev",
 then add any non-standard packages like pdf4tcl.

In my C library "cobtcl" I have (Cobol Friendly) STARTTCL, STOPTCL, TCLEVAL, TCLSETVAR, TCLGETVAR, and TCLEVALFILE.
EXAMPLE of the problem, first without cobtcl library, calling the Tcl* functions directly from OpenCobol:

$ cobc -x -free -ffunctions-all -I/usr/include/tcl8.5 -ltcl8.5 getlotto.cob
$ ./getlotto
libcob: Cannot find module 'Tcl_FindExecutable'
$

I have successfully compiled and linked same as above, and it ran fine on other Linux machines.
But on some machines it does not work, "can't find module" and I have no idea why!

$ ldd getlotto
    linux-gate.so.1 =>  (0xb77e0000)
    libcob.so.1 => /usr/local/lib/libcob.so.1 (0xb778e000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75e5000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb75b8000)
    libgmp.so.10 => /usr/lib/i386-linux-gnu/libgmp.so.10 (0xb7539000)
    libncurses.so.5 => /lib/i386-linux-gnu/libncurses.so.5 (0xb7517000)
    libtinfo.so.5 => /lib/i386-linux-gnu/libtinfo.so.5 (0xb74f8000)
    libdb-5.1.so => /usr/lib/i386-linux-gnu/libdb-5.1.so (0xb7370000)
    libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb736a000)
    /lib/ld-linux.so.2 (0xb77e1000)
    libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb734f000)

I know that Tcl_FindExecutable is in libtcl8.5.so, and -ltcl8.5 is correct, but 'ldd' says that getlotto is not even looking for libtcl8.5.so ..
and therefore coblib does not find it, can't find it.

However, if statically linked, then it does find it.
Not wanting to compile the entire libtcl into my cobol program,
I instead write a small C wrapper, cobtcl.c, statically linking cobtcl.o seems to make it work.
This makes sense too me, because coblib is not calling the dynamically linked functions, clib is calling those.
coblib is only calling the statically liked functions in cobtcl.o

So I modified getlotto.cob to call my cobtcl C functions, STARTTCL, and so on... saved it as newgetlotto.cob

$ cobc -c  -I/usr/include/tcl8.5 cobtcl.c
$ cobc -x -ffunctions-all -free -ltcl8.5 newgetlotto.cob cobtcl.o
$ ./newgetlotto
Most recent drawing: Lotto Texas,7,17,2013,40,8,3,12,15,25
$
$ ldd newgetlotto
    linux-gate.so.1 =>  (0xb7749000)
    libcob.so.1 => /usr/local/lib/libcob.so.1 (0xb76f7000)
    libtcl8.5.so.0 => /usr/lib/libtcl8.5.so.0 (0xb75dd000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7433000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7407000)
    libgmp.so.10 => /usr/lib/i386-linux-gnu/libgmp.so.10 (0xb7388000)
    libncurses.so.5 => /lib/i386-linux-gnu/libncurses.so.5 (0xb7366000)
    libtinfo.so.5 => /lib/i386-linux-gnu/libtinfo.so.5 (0xb7347000)
    libdb-5.1.so => /usr/lib/i386-linux-gnu/libdb-5.1.so (0xb71be000)
    libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb71b9000)
    libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb719e000)
    /lib/ld-linux.so.2 (0xb774a000)

Now it works!

more rambling's..............

BTW: Patrick, if you want a complete copy these examples cobtcl.c, just email me.. that goes for anyone.
The lotto program is just a dumb example that anyone can follow,
I use Tcl for all kinds misc functions, like access to sql data, getting resources from web servers, status of files, creating PDF's, and much more.

Another example encrypt/decrypt a password.
These examples are AcuCobol, but the same exact source works with OpenCOBOL.
In OpenCobol I would have used the trim function instead of "delimited by size" and "delimited by space"
Here we Execute two pre-written Tcl functions known as 'procs', EncryptData, and DecryptData.
So yes, you can develop all your Tcl procs, store them in one file, ea. myprocs.tcl.
Then load all these procs into the interpreter using TCLEVALFILE after calling STARTTCL.
Then anytime within your cobol app, you can execute a specific proc, and pass parms using TCLEVAL.

*>---------------------------------------------------------
 Encrypt-string.
     Move Spaces To Encrypted-string.
     Perform Set-Encryption-Key.
     Move LOW-VALUES TO TCL-BUFFER.
     Move 0 To TCL-RESULT.
*> =========
*> EncryptData takes two parms, a string, and a length.
*> if you were in the tclsh shell, the command would look like so:
*>   
set cipher [EncryptData mypasswd 8]
*> now the var 'cipher' contains the encrypted value of mypasswd

*> =========
     String "set cipher [EncryptData " Delimited By Size
             Cleartext-String          Delimited By " "
             " 8]"                     delimited by size
              into TCL-BUFFER.

     CALL "TCLEVAL" USING TCL-INTR TCL-BUFFER TCL-RESULT.

     MOVE LOW-VALUES TO TCL-VARNAME
     STRING "cipher" DELIMITED BY SIZE INTO TCL-VARNAME.
     MOVE SPACES TO TCL-BUFFER.
     CALL "TCLGETVAR" USING TCL-INTR TCL-VARNAME TCL-BUFFER.

     Move Spaces To Encrypted-string.
     String TCL-BUFFER delimited by x"00" into Encrypted-string.

*>---------------------------------------------------------
 Decrypt-String.
     Perform Set-Encryption-Key.
     Move LOW-VALUES TO TCL-BUFFER.
     MOVE LOW-VALUES TO TCL-VARNAME
     Move 0 To TCL-RESULT.
     Move Spaces To ClearText-String.

     String "set CLEARTEXT [DecryptData " delimited by size
            Encrypted-string      delimited by " "
            " 8]"                 delimited by size
        into TCL-BUFFER.

     CALL "TCLEVAL" USING TCL-INTR TCL-BUFFER TCL-RESULT.

     STRING "CLEARTEXT" DELIMITED BY SIZE INTO TCL-VARNAME
     MOVE SPACES TO TCL-BUFFER.
     CALL "TCLGETVAR" USING TCL-INTR TCL-VARNAME TCL-BUFFER.

     String TCL-BUFFER delimited by x"00" into ClearText-String.

*>---------------------------------------------------------
 Set-Encryption-Key.
     Move LOW-VALUES TO TCL-BUFFER.
     MOVE LOW-VALUES TO TCL-VARNAME.
     Move Spaces To MY-KEY.
     String AUTHSESS-USER Delimited By Space
            AUTHSESS-FWTYPE AUTHSESS-LOG-ON-LOC AUTHSESS-HOME-LOC Delimited By Size
            AUTHSESS-FWIP Delimited By "."
      Into MY-KEY.
     Inspect MY-KEY replacing all " " by "0".

     String MY-KEY
        Delimited By Size InTo TCL-BUFFER.

     STRING "TIWAPPKEY"
        Delimited By Size InTo TCL-VARNAME.

     CALL "TCLSETVAR" USING TCL-INTR TCL-VARNAME TCL-BUFFER.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]