2928

Passing python strings to Fortran subroutine using ctypes

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.

Answer1:

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.

Recommend

  • C++ - Python Binding with ctypes - Return multiple values in function
  • Eclipse and Python 3: why does printf() from ctypes display in console output after subsequent print
  • How is the attribute of the loader instance `cdll` created?
  • Catch exception in ctypes based on C-exit code
  • Ctypes: Mapping a returned pointer to a structure
  • Create a valid shared library in C
  • XGBoost installation issues for Python Anaconda Windows 10 (18 May 2018)
  • Request.el “cannot create connection to api.stackexchange.com”
  • Passing python strings to Fortran subroutine using ctypes
  • How can I use ctypes to pass a byteArray into a C function that takes a char* as its argument?
  • Android: NoSuchMethodError with static method in interface (using Retrolambda)
  • The GitHub.app for Mac crashes every time, if a local repository is loaded
  • Facebook iPhone SDK, App crashed in pre iOS 4.2, But works fine in iOS 4.2+
  • Memory allocation profilers for managed and unmanaged code?
  • Pointer on ctypes to use OpenCV on Python 3.1
  • Compile C++ source to a .dll
  • C++ Static Initializer - Is it thread safe
  • dll not loading in python
  • iPhone - UIWebView multiple locks
  • Is it necessary to call system.loadLibrary explicitly for accessing the native methods in a NativeAc
  • pymongo replication secondary readreference not work
  • my tic-tac-toe program in matlab does not work [closed]
  • Changing Jupyter Notebook start up folder by modifying “start in” not working any more
  • Using Generics on right hand side in Java 6?
  • import scipy.sparse failed
  • How to use function wrapper in mustache.php?
  • During installation of Django, why do I keep getting ImportError: No module named django?
  • where do I find the xml.dom python package for the python-2.6.0-8.9.28 and I have a suse/x86_64 vers
  • Python pickle not one-to-one: different pickles give same object
  • MySQL Order by column = x, column asc?
  • Matplotlib draw Spline from multiple points
  • Why winpcap requires both .lib and .dll to run?
  • Return words with double consecutive letters
  • Python: how to group similar lists together in a list of lists?
  • Busy indicator not showing up in wpf window [duplicate]