我正在尝试使用P/invoke从C#代码调用FORTRAN77子例程 - 如果您有兴趣,我正在尝试包装ARPACK库(http://www.caam.rice.edu/software/ARPACK)提供的某些功能。 我有两个问题。
首先,我无法在任何地方找到有关此上下文中类型编组的清晰说明。 更具体地说,这是我FORTRAN子程序中声明的类型:
subroutine getEigenVectors
& ( Matrix, n, which, nev, ncv, maxn, maxnev, maxncv, ldv, v, d)
c %------------------%
c | Scalar Arguments |
c %------------------%
character which*2
integer n, nev, maxn, maxnev, maxncv, ldv
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& Matrix(n,n), v(ldv,maxncv), d(maxncv,2)
我在这里找到了一些有价值的信息: 如何在Fortran中为字符类型进行MarshalAs?,从中我得出(可能是错误的)结论,我应该使用:
[MarshalAs(UnmanagedType.I4)] int
传递整数[MarshalAs(UnmanagedType.LPArray)] byte[]
传递字符字符串
然而,我完全不知道该怎么处理Real
数组。 有人对此有任何想法吗?
其次,我对是否应该将参数作为引用传递感到困惑。我绝不熟悉FORTRAN - 我知道,这使得任务有些困难; 然而,只有ARPACK才能做我想做的事情。我确实在某个地方读到过FORTRAN子例程默认将所有参数作为引用的说法。因此,我是否应该将所有参数都作为引用传递?
感谢您的帮助! Guillaume
编辑(8/6/11)
这是我的最终看法:
[DllImport("Arpack.dll", EntryPoint = "#140")]
private static extern void getEigenVectors(
[MarshalAs(UnmanagedType.LPArray)] ref float[,] matrix,
[MarshalAs(UnmanagedType.I4)] ref int n,
[MarshalAs(UnmanagedType.LPArray)] ref byte[] which,
[MarshalAs(UnmanagedType.I4)] int whichLength,
[MarshalAs(UnmanagedType.I4)] ref int nev,
[MarshalAs(UnmanagedType.I4)] ref int ncv,
[MarshalAs(UnmanagedType.I4)] ref int maxn,
[MarshalAs(UnmanagedType.I4)] ref int maxnev,
[MarshalAs(UnmanagedType.I4)] ref int maxncv,
[MarshalAs(UnmanagedType.I4)] ref int ldv,
[MarshalAs(UnmanagedType.LPArray)] ref float[,] v,
[MarshalAs(UnmanagedType.LPArray)] ref float[,] d
);
我在这里做了几件事情:
- Pass
int
objects marshalled asUnmanagedType.I4
to match FORTRANinteger
objects - Pass
float[,]
objects of size (m, n) and marshalled asUnmanagedType.LPArray
to match FORTRANReal(n,m)
objects Pass
byte[]
objects obtained marshalled asUnmanagedType.LPArray
to match FORTRANCharacter*n
objects. Thebyte[]
objects are computed as follows:System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); byte[] which = encoding.GetBytes(myString);
- Pass an
int
object BY VALUE and marshalled asUnmanagedType.I4
to indicate the length of the string. Note that I tried to put that argument right after the string as well as at the end of the arguments list.
float
会自动转换为REAL
。另外,请查看您的编译器是否具有“!DEC$ ATTRIBUTE VALUE”规范,以减少*C#*中“ref”参数的数量。 - John Alexioufloat[,]
传递。此外,数组已经是引用,不需要使用ref
。Fortran 中的REAL :: A(2,2)
会被传递为具有 4 个元素的float A[]
。按顺序,它们是A11
、A21
、A12
、A22
,因为 FORTRAN 在元素排序方面与 C 不同。 - John Alexiou