Fortran Strings to Go

121 Views Asked by At

I've been trying to pass a Fortran string to a shared C library generated from GO using buildmode c-shared. I've unsuccessfully tried to define a derived type to match what the generated function signature expects. I'm trying to avoid passing the strings to my own C glue code (that takes a Fortran string and converts it to a go string and calls the go library) if possible.

My GO signature

//export MyFunc
func MyFunc(str1, str2 string) bool {

The generated GO header file defines

mylib.h

#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
#endif

#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef _GoString_ GoString;
#endif

typedef unsigned char GoUint8;

And my function signature

extern GoUint8 MyFunc(GoString str1, GoString str2);

My attempt

module go_types
    use iso_c_binding
    type, bind(c) :: go_string
        type(c_ptr) :: msg
        integer(c_ptrdiff_t) :: n
    end type go_string
end module go_types

program test_go
    ! use iso_c_binding, only: C_NULL_CHAR, c_char !! Use to terminate strings
    use, intrinsic :: iso_c_binding
    use go_types
    implicit none

    interface        
        integer(c_ptrdiff_t) function MyFunc(str1, str2) bind(C, name="MyFunc")
            use go_types            
            type(go_string) :: str1
            type(go_string) :: str2
        end function Validate
        
    end interface

    type(go_string) :: str1, str2
    character(len=25), target :: fortstr1, fortstr2

    integer :: ret

    fortstr1 = "Bar"//C_NULL_CHAR
    str1%msg = c_loc(fortstr1)
    str1%n = len(trim(fortstr1))


    fortstr2 = "Foo"//C_NULL_CHAR
    str2%msg = c_loc(fortstr2)
    str2%n = len(trim(fortstr2))

    ret = MyFunc(str1, str2)
    print *, 'return code:', ret
contains

end program

The code compiles fine but when I try to access the string in the GO library I get

runtime: out of memory: cannot allocate 140732811706368-byte block (3833856 in use)
fatal error: out of memory

goroutine 17 [running, locked to thread]:
runtime.throw({0x10698a55a, 0x400})
        /usr/local/Cellar/go/1.17/libexec/src/runtime/panic.go:1198 +0x71 fp=0xc000056990 sp=0xc000056960 pc=0x1068ceaf1
runtime.(*mcache).allocLarge(0x106f1b040, 0x7ffee9366000, 0x1, 0x1)
        /usr/local/Cellar/go/1.17/libexec/src/runtime/mcache.go:229 +0x22e fp=0xc0000569f0 sp=0xc000056990 pc=0x1068b28ee
runtime.mallocgc(0x7ffee9366000, 0x0, 0x0)
        /usr/local/Cellar/go/1.17/libexec/src/runtime/malloc.go:1082 +0x5c5 fp=0xc000056a70 sp=0xc0000569f0 pc=0x1068a9ba5
runtime.growslice(0x203000, {0xc0000b2240, 0x12da19c40, 0x12da19b00}, 0x0)
        /usr/local/Cellar/go/1.17/libexec/src/runtime/slice.go:261 +0x4ac fp=0xc000056ad8 sp=0xc000056a70 pc=0x1068e56cc
...

I've also tried a few permutations with msg being character(kind=c_char) instead of a c_ptr but it doesn't seem to work either.

0

There are 0 best solutions below