如何更便捷实现C#与Fortran固定大小字符串的封送?
Fortran与C#互操作:固定长度无终止符字符串的封送优化需求
我维护一个基于Fortran的代码库,同时用C#编写互操作代码。Fortran代码中包含大量结构体,所有数组与字符串均为固定大小,且这些结构体在C#与Fortran中存在重复定义。示例如下:
Fortran结构体定义
type :: my_type character(4) :: foo end type
对应C#结构体定义
[StructLayout(LayoutKind.Sequential)] public struct MyType { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] byte[] Foo; }
我们使用byte[]是因为Fortran中的character(4)是不含空终止符的4字符字符串。这种方式虽然可行,但在C#代码中需要频繁在byte[]与string间转换,且数组默认值为null,使用体验很差。若将Foo直接声明为C#的string,封送器会自动在末尾添加\0,导致Fortran代码出错。
我尝试用自定义struct包装byte[]并声明隐式字符串转换,简化类型转换操作:
[StructLayout(LayoutKind.Sequential)] public struct MyStringWrapper { private byte[] value; public static implicit operator string(MyStringWrapper w) => Encoding.ASCII.GetString(w.value); public static implicit operator MyStringWrapper(string s) { MyStringWrapper w; w.value = Encoding.ASCII.GetBytes(s); return w; } }
但现在遇到了问题:不知道如何在MyType中为MyStringWrapper类型的字段设置属性,以实现底层value作为固定缓冲区的正确封送。需要注意的是,MyStringWrapper的实例并非都具有相同的固定大小。
我寻求以下任一解决方案:
- 直接将字段声明为
string,使其被封送为无空终止符的固定大小ASCII值 - 让上述包装器可以传递封送所需的属性,实现正常封送
- 其他可行的实现方式
另外,这类固定大小字符串的声明大约有200个,目前存在数十种不同长度,我希望避免为每个长度都单独声明新类型。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

