从 C# 调用 FORTRAN dll 并将值分配给结构数组
我可以将 C#
结构传递到 FORTRAN
中。我什至可以将 C#
结构数组作为 FORTRAN
中的 TYPE()
数组传递。当我尝试将值返回到 C#
时,我遇到了麻烦。下面是一个示例:
Fortran dll 是:
MODULE TESTING
TYPE VALUEREF
INTEGER*4 :: A
ENDTYPE VALUEREF
CONTAINS
SUBROUTINE TEST_REF(T,N)
!DEC$ ATTRIBUTES DLLEXPORT :: TEST_REF
!DEC$ ATTRIBUTES ALIAS:'TEST_REF' :: TEST_REF
!DEC$ ATTRIBUTES VALUE :: N
IMPLICIT NONE
INTEGER*4 :: A,I,N
TYPE(VALUEREF) :: T(N)
A = 100
DO I=1,N
T(I)%A = A + I
END DO
END SUBROUTINE
END MODULE
期望结果的 C#
调用函数是:
[StructLayout(LayoutKind.Sequential)]
public struct ValueRef
{
public int a;
}
[DllImport("mathlib.dll")]
static extern void TEST_REF(ValueRef[] t, int n);
void Main()
{
ValueRef[] T = new ValueRef[4];
for (int i = 0; i < T.Length; i++)
{
T[i].a = i;
}
Console.WriteLine("Initialize");
for (int i = 0; i < T.Length; i++)
{
Console.WriteLine(" A={0}", T[i].a);
}
Console.WriteLine("Call Fortran");
TEST_REF(T, T.Length);
for (int i = 0; i < T.Length; i++)
{
Console.WriteLine(" A={0}", T[i].a);
}
}
结果:
Initialize
A=0
A=1
A=2
A=3
Call Fortran
A=0
A=1
A=2
A=3
通过 FORTRAN 代码进行调试,我看到从 C#
传递的初始值> 到 FORTRAN
就可以了。这些值被新值覆盖,并且控制权被传递回 C#
,其中旧值仍然包含在 ValueRef
实例中。
为什么我可以以类似的方式传递和返回 float
或 int
数组,就很好了。我可以使用 ref
关键字传递和返回单数结构,并且我可以传递但不能返回和 struct
数组?
PS。我正在使用 Compaq Visual Fortran 6.5 & .NET 3.5
PS2。我很感激对此的任何评论/想法。我的项目完成了 95%,现在遇到了这个问题。这个项目的重点是尽可能多地使用结构来减少传递给函数的参数 #of 并保留 OOP 设计的某些方面。
I can pass a C#
struct into FORTRAN
just fine. I can even pass an array of a C#
struct as an array of TYPE()
in FORTRAN
. Where I run into trouble is when I tried to return values back into C#
. Here is an example:
The fortran dll is:
MODULE TESTING
TYPE VALUEREF
INTEGER*4 :: A
ENDTYPE VALUEREF
CONTAINS
SUBROUTINE TEST_REF(T,N)
!DEC$ ATTRIBUTES DLLEXPORT :: TEST_REF
!DEC$ ATTRIBUTES ALIAS:'TEST_REF' :: TEST_REF
!DEC$ ATTRIBUTES VALUE :: N
IMPLICIT NONE
INTEGER*4 :: A,I,N
TYPE(VALUEREF) :: T(N)
A = 100
DO I=1,N
T(I)%A = A + I
END DO
END SUBROUTINE
END MODULE
and the C#
calling function that expects results is:
[StructLayout(LayoutKind.Sequential)]
public struct ValueRef
{
public int a;
}
[DllImport("mathlib.dll")]
static extern void TEST_REF(ValueRef[] t, int n);
void Main()
{
ValueRef[] T = new ValueRef[4];
for (int i = 0; i < T.Length; i++)
{
T[i].a = i;
}
Console.WriteLine("Initialize");
for (int i = 0; i < T.Length; i++)
{
Console.WriteLine(" A={0}", T[i].a);
}
Console.WriteLine("Call Fortran");
TEST_REF(T, T.Length);
for (int i = 0; i < T.Length; i++)
{
Console.WriteLine(" A={0}", T[i].a);
}
}
With results:
Initialize
A=0
A=1
A=2
A=3
Call Fortran
A=0
A=1
A=2
A=3
Debugging through the FORTRAN code, I see the initial values pass from C#
to FORTRAN
just fine. The the values get overridden with new values and control is passed back into C#
where the old values are still contained within the ValueRef
instances.
Why is it that I can pass and return an array of float
, or int
in a similar fashion, just fine. and I can pass and return singular structures with ref
keyword, and I can pass but not return and array of struct
?
PS. I am using Compaq Visual Fortran 6.5 & .NET 3.5
PS2. I appreciate any comments/ideas on this. I am 95% done with my project, and now I run into this issue. The whole point of this project is to use structures as much as possible to reduce the #of arguments passed to functions and retain certain aspects of OOP design.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我过去使用指针而不是数组来完成此操作。我认为您的结构正在为 P/Invoke 调用进行复制:
您需要在调用方法之前固定数组。
编辑:
根据评论,解决方案是将外部声明为
Here is a MSDN 有关数组编组的参考,以及它们如何默认为
[In]
。I have done this in the past using a pointer, not an array. I think that your structures are being copied for the P/Invoke call:
You will need to pin your array before calling the method.
Edit:
Based on the comments the solution is to declare the external as
Here is a MSDN reference on Marshaling of arrays, and how they default to
[In]
.