Why am I getting this error? : wrong type

I have a Python driver calling a Fortran subroutine. The subroutine has 1 character, then 3 integers. Before I added the character variable at the start and didn’t have the argtypes call, it ran fine. But adding the character (and its length) plus the artgtypes call at the start gives a TypeError:

import ctypes as ct
lib = ct.CDLL('FTN_lib.dll')
fs = getattr(lib,'PY_OBJFUN_MOD_mp_GETSIZE')
fs.restype = None
fs.argtypes = [ct.c_char_p,ct.c_int,ct.c_int,ct.c_int,ct.c_int]
x = b'x ' + sys.argv[1].encode('UTF-8') + b' debug=900'
n = ct.c_int(0)
nl = ct.c_int(0)
nnl = ct.c_int(0)
fs(x, len(x), ct.byref(n), ct.byref(nl), ct.byref(nnl))
fs(x, len(x), ct.byref(n), ct.byref(nl), ct.byref(nnl))

ctypes.ArgumentError: argument 3: <class ‘TypeError’>: wrong type

It seems the addition of fs.argtypes is causing the problem. The test code didn’t have it, and it worked fine. Adding fs.argtypes causes the test code to fail too. Hence there is some problem using ct.c_int construct which is used as ct_byref in the call.

The Fortran code header is:

  subroutine getsize(file,n,nl,nnl)
    implicit none
    character(*), intent(in ) :: file
    integer     , intent(out) :: n   
    integer     , intent(out) :: nl  
    integer     , intent(out) :: nnl 

  • 1

    “The subroutine has 1 character, then 3 integers” – yet you provide an argtypes list of 1 character and 4 integers – is the last integer supposed to be the return type? If so, assign it to restype instead

    – 

  • @MathiasR.Jessen no there are 5 types in argtypes (char, its length, and 3 ints). In Fortran a character is sent from Python (or C) as a char and a length. Hence a Fortran character has two argument in Python. There is no restype, it is a subroutine.

    – 

  • Gotcha. Try passing ct.pointer(n) instead of ct.byref(n)

    – 

  • @MathiasR.Jessen nope exactly the same problem. I’m using ct.byref is this worked in my test example, created from this thread stackoverflow.com/questions/77989853/…. The syntax fs(ct.byref(n), ct.byref(nl), ct.byref(nnl)) works fine without the character in Fortran / Python. Just getting this error when I add the char.

    – 

  • Can you share the argument declarations from the subroutine?

    – 

Fortran passes the integers by reference instead of by value. argtypes for the integer parameters should be ct.POINTER(ct.c_int).

Note: A comment on another answer indicates the string size should be int32 on 32-bit systems and int64 on64-bit. I’d use c_size_t. It also says string lengths are added to the end of the parameter list and not interleaved. I don’t have Fortran to test.

Try:

fs.argtypes = ct.c_char_p, ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.c_size_t
x = b'x ' + sys.argv[1].encode('UTF-8') + b' debug=900'
n = ct.c_int(0)
nl = ct.c_int(0)
nnl = ct.c_int(0)
fs(x, ct.byref(n), ct.byref(nl), ct.byref(nnl), len(x))

Leave a Comment