2

I'm trying to pass arguments to a Fortran subroutine in a shared library using ctypes. Now here's my simple fortran code:

MODULE test_module
INCLUDES
SUBROUTINE fstr_test(file_or_extension, ierr, iopen)
   IMPLICIT NONE
   INTEGER, INTENT(out) :: ierr
   INTEGER, OPTIONAL :: iopen
   CHARACTER(LEN=*), INTENT(in) :: file_or_extension
   WRITE(6,*) file_or_extension,ierr,iopen
   RETURN
END SUBROUTINE fstr_test
END MODULE test_module

I compile this with

gcc -shared -fPIC -o libtest.o fstr_test.f90

This seems to work fine, I can in fact load the shared library in Python 3. Here's non-crashing code:

from ctypes import *
libtest = cdll.LoadLibrary("libtest.so")
f = libtest.test_module_MOD__fstr_test
file = b'wout_li383.nc'
ierr = c_int(0)
iopen = c_int(0)
cfile=c_char_p(b"test_str")
f(cfile,byref(ierr),byref(iopen))

However, I can't seem to pass the string properly. In the form above the string is empty and the two integers print properly to the console. Basically the only progress I'm made is getting Python to crash. I tried the solution here:

Passing string to Fortran DLL using ctypes and Python

but it doesn't seem to work for me, maybe because it's talking about Python 2?

For example

f.argtype = [c_char_p,c_int_c_int]
c = c_char_p(b"test.txt")
f(c,byref(ierr),byref(iopen))

Doesn't crash the kernel but the string is empty. Changing to byref:

f.argtype = [c_char_p,c_int_c_int]
c = c_char_p(b"test.txt")
f(byref(c),byref(ierr),byref(iopen))

same effect. Now if I try to pass the length by adding the length argument and passing it I get a message of a "Dead Kernel" and I have to restart the kernel. There's no error message per-se.

f.argtype = [c_char_p,c_int,c_int_c_int]
file = b'text.txt'
c = c_char_p(file)
c_len = c_int(len(file))
f(c,byref(c_len),byref(ierr),byref(iopen))

Hope this clarifies. I'm not getting an error message, the kernel is just dying.

7
  • The linked question's answer talks about passing a "hidden" argument for the string's length (a common approach when not using C-interoperable character variables). You don't do that here? Commented Feb 19, 2017 at 16:18
  • Why it does notbseem to work? Error message? Wrong results? Show them. Commented Feb 19, 2017 at 19:04
  • If I include the string length as a hidden variable the Kernel crashes. Commented Feb 20, 2017 at 2:46
  • Why not f2py? Can't you recompile your DLL? Commented Feb 20, 2017 at 7:34
  • "If I include the string length as a hidden variable the Kernel crashes." Show the code and the error message then! (I already asked before.) Commented Feb 20, 2017 at 9:40

1 Answer 1

4

So a few issues, one the hidden length (at least with gfortran unknown what the other compilers do) should go at the end of the argument list. You don't need the byref on it either and don't wrap the byte-string in c_char_p

Changing the ierr variable in the subroutine

  SUBROUTINE fstr_test(file_or_extension, ierr, iopen)
     IMPLICIT NONE
     INTEGER, INTENT(out) :: ierr
     INTEGER, OPTIONAL :: iopen
     CHARACTER(LEN=*), INTENT(in) :: file_or_extension
     WRITE(6,*) file_or_extension,ierr,iopen
     ierr=1
     RETURN
  END SUBROUTINE fstr_test

and

gfortran -shared -fPIC -o libtest.so fstr_test.f90

Then the python code should be this:

import ctypes

lib=ctypes.CDLL("./libtest.so")
f=getattr(lib,'__test_module_MOD_fstr_test')

f.argtypes=[ctypes.c_char_p,ctypes.c_int,ctypes.c_int,ctypes.c_int]
f.restype=None

x=b'abcdef'
ierr=ctypes.c_int(0)
iopen=0
f(x,ctypes.byref(ierr),iopen,len(x))
print(ierr.value)

Though i haven't got the optional argument working let, so i've added an empty int, this should yet you pass the string in and get ierr out.

Sign up to request clarification or add additional context in comments.

2 Comments

Should it be argparse or argtypes in your example? BTW- Thanks it seemed to work just fine.
Good catch, it should be argtypes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.