lionel319
lionel319

Reputation: 1256

trying to support python code in tcl

I'm new to all of this thing, and so please excuse me if i kinda did something stupid here. Treat me and explain to me as if i'm a total noob would be helpful.

I have a simple function written in python, filename a.pyx:-

#!/usr/bin/env python

import os
import sys

def get_syspath():
    ret = sys.path
    print "Syspath:{}".format(ret)
    return ret

I want it to be able to be used by tcl.

I read thru the cython page, and followed.

I ran this:-

cython -o a.c a.pyx

I then ran this command to generate the object file a.o:-

gcc -fpic -c a.c -I/usr/local/include -I/tools/share/python/2.7.1/linux64/include/python2.7 

And then ran this to generate the so file a.so:-

gcc -shared a.o -o a.so

when i load it from a tclsh, it failed.

$tclsh
% load ./a.so
couldn't load file "./a.so": ./a.so: undefined symbol: PyExc_RuntimeError

Am i taking the correct path here? If not, can please explain to me what went wrong, and what should I be doing?

Thanks in advance.

Upvotes: 1

Views: 188

Answers (2)

schlenk
schlenk

Reputation: 7237

Maybe have a look at tclpython or libtclpy.

Both allow calling Python code from Tcl.

But if you wanted to wrap things in a nicer way, e.g. have nicer already wrapped APIs, maybe you should also look at Elmer, which seems to aim at the task your attempting.

Upvotes: 1

Donal Fellows
Donal Fellows

Reputation: 137567

The object code needs to be linked to the libraries it depends on when you're building the loadable library. This means adding appropriate -l... options and possibly some -L... options as well. I'm guessing that the option will be something like -lpython27 or something like that (which links to a libpython27.so somewhere on your library search path; the library search path is modified with the -L... options), but I don't know. Paths will depend a lot on exactly how your system is set up and experimentation is likely required on your half.

It still probably won't work as a loadable library in Tcl. Tcl expects there to be a library initialisation function (in your case, it will look for A_Init) that takes a Tcl_Interp* as its only argument so that the library can install the commands it defines into the Tcl interpreter context. I would be astonished if Python made such a thing by default. It's not failing with that for you yet because the failures are still happening during the internal dlopen() call and not the dlsym() call, but I can confidently predict that you'll still face them.

The easiest way to “integrate” that sort of functionality is by running the command in a subprocess.

Here's the Python code you might use:

import os
import sys

print sys.path

And here's the Tcl code to use it:

set syspath [exec python /path/to/yourcode.py]
# If it is in the same directory as this script, use this:
#set syspath [exec python [file join [file dirname [info script]] yourcode.py]]

It's not the most efficient way, but it's super-easy to make it work since you don't have to solve the compilation and linking of the two languages. It's programmer-efficient

Upvotes: 2

Related Questions