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.