无需C粘合代码将Fortran字符串传入Go生成的C共享库问题求解
问题原因与解决方案
代码存在4个核心错误导致参数传递异常,Go侧拿到的字符串长度是栈上垃圾值,才会触发超大内存分配报错:
- 结构体参数传递方式错误:C头文件中
MyFunc的参数是GoString值传递,而Fortran默认参数传递为引用传递,导致Go侧拿到的结构体内容完全错误。 - 接口定义不匹配:接口块中绑定的函数名是
MyFunc,但结束语句错误写为end function Validate,导致函数绑定失效,调用逻辑完全错乱。 - 返回值类型错误:Go导出函数返回值是
GoUint8(对应C的unsigned char),错误声明为integer(c_ptrdiff_t)会破坏栈结构,进一步导致参数传递异常。 - 不必要的
C_NULL_CHAR后缀:Go字符串不需要以NULL结尾,追加空字符反而可能导致字符串内容不符合预期。
修正后的完整代码
module go_types use iso_c_binding implicit none ! 和C头文件的GoString结构体内存布局完全对齐 type, bind(c) :: go_string type(c_ptr) :: p integer(c_ptrdiff_t) :: n end type go_string end module go_types program test_go use, intrinsic :: iso_c_binding use go_types implicit none ! 修正接口定义:返回值类型正确,参数加value属性声明为值传递 interface function MyFunc(str1, str2) bind(C, name="MyFunc") use iso_c_binding use go_types integer(c_uint8_t) :: MyFunc type(go_string), intent(in), value :: str1 type(go_string), intent(in), value :: str2 end function MyFunc end interface type(go_string) :: str1, str2 character(len=25), target :: fortstr1, fortstr2 integer(c_uint8_t) :: ret ! 不需要追加C_NULL_CHAR,Go字符串不依赖空结束符 fortstr1 = "Bar" str1%p = c_loc(fortstr1) ! 直接取trim后的实际有效长度 str1%n = len_trim(fortstr1) fortstr2 = "Foo" str2%p = c_loc(fortstr2) str2%n = len_trim(fortstr2) ret = MyFunc(str1, str2) print *, 'return code:', ret end program test_go
补充说明
如果你的Fortran编译器要求显式设置字符串为C字符类型,可以将字符串声明改为character(kind=c_char, len=25), target :: fortstr1, fortstr2,绝大多数情况下默认的字符类型和c_char是兼容的。
内容的提问来源于stack exchange,提问作者Guillaume
相关产品推荐
相关产品推荐

