Robert L. Parker和Philip B. Stark在Fortran中有一个代码:
subroutine bv(key, m, n, a, b, bl, bu, x, w, act, zz, istate, loopA)
implicit double precision (a-h, o-z)
! x is an unknown n-vector
! a is a given m by n matrix
! b is a given m-vector
! bl is a given n-vector of lower bounds on the components of x.
! bu is a given n-vector of upper bounds on the components of x.
! key = 0
! ---Output parameters:
! x the solution vector.
! w(1) the minimum 2-norm || a.x-b ||.
! istate vector indicating which components of x are active
! loopA number of iterations taken in the main loop, Loop A.
! ---Working arrays:
! w dimension n. act dimension m*(mm+2). mm=min(m,n).
! zz dimension m. istate dimension n+1.
我试图从C#中的dll调用该函数,例如:
class Program
{
[DllImport("bv.dll", CallingConvention = CallingConvention.StdCall )]
public static extern void bvls(
int key, //key = 0, the subroutine solves the problem from scratch. If key > 0 the routine initializes using the user's guess about which components of x are `active'
int m,
int n,
double[] a, // m by n matrix
double[] b, // m-vector
double[] bl, //n-vector of lower bounds on the components of x.
double[] bu, //n-vector of upper bounds on the components of x.
ref double[] x, //unknown n-vector
//Working arrays:
ref double[] w, //dimension n
double[] act, //dimension m*(mm+2). mm=min(m,n).
double[] zz, //dimension m
ref double[] istate, //dimension n+1.
ref int loopA // number of iterations taken in the main loop, Loop A.
);
static void Main(string[] args)
{
double[] a = new double[3 * 3] { //M*N
1.0, 10.0, 10.0,
2.0, 18.0, 16.0,
1.8, 69.0, 16.0
};
double[] b = new double[3] { //LDB*NRHS
4.3, 6.8, 1.0,
};
double[] bl = new double[3];
double[] bu = new double[3];
double[] x = new double[3];
double[] w = new double[3];
double[] act = new double[3* 5]; //dimension m*(mm+2). mm=min(m,n).
double[] zz = new double[3];
double[] istate = new double[4];
int loopA =0;
Program.bv(0, 3, 3, a, b, bl, bu, ref x, ref w, act, zz, ref istate, ref loopA);
for (int j = 0; j < 3; j++)
Console.Write(" \t" + x[j]);
}
}
但是在执行代码时我得到
EntryPointNotFoundException: Entry point was not found. in 'bv' on file 'bv.dll'.
myProject.Program.bv(Int32 key, Int32 m, Int32 n, Double[] a, Double[] b, Double[] bl, Double[] bu, Double[]& x, Double[]& w, Double[] act, Double[] zz, Double[]& istate, Int32& loopA)
基本上我有两个问题,如何使它起作用?和其他问题,它是否正确我定义函数的方式
[DllImport("bv.dll", CallingConvention = CallingConvention.StdCall )]
public static extern void bvls(...)
基于fortran代码的常规信息?
使用依赖行者时,我得到:
我怀疑dll不正确并且没有例程,是否可以检查dll是否以正确的方式生成?
在尝试了ILSpy之后,我得到了以下提示似乎不正确,您能否建议如何正确生成dll文件?,ILSpy是否告诉bvlsFortran是我应使用的函数?我尝试过,但无法正常工作
在FORTRAN
以下尝试:
MODULE CALCBV
INTEGER, PARAMETER :: sp = SELECTED_REAL_KIND(p=6,r=37) ! IEEE Single Precision (32-bit)
INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(p=15,r=307) ! IEEE Double Precision (64-bit)
CONTAINS
subroutine bv(key, m, n, a, b, bl, bu, x, w, act, zz, istate, loopA)
IMPLICIT NONE
!DEC$ ATTRIBUTES DLLEXPORT :: bv
!DEC$ ATTRIBUTES ALIAS:'BV' :: bv
!DEC$ ATTRIBUTES VALUE :: key, m, n
INTEGER, INTENT(IN) :: key, m, n
REAL(dp), INTENT(IN) :: a(m,n), b(m), bl(n), bu(n)
REAL(dp), INTENT(OUT) :: x(n), w(n)
REAL(dp), INTENT(IN) :: act(m,MIN(m,n)+2), zz(m)
INTEGER, INTENT(OUT) :: istate(n+1)
INTEGER, INTENT(OUT) :: loopA
! DO CALC HERE
end subroutine
END MODULE
然后使用以下命令调用它C#
:
[DllImport("bv.dll", CallingConvention=CallingConvention.Cdecl, EntryPoint="BV")]
static extern void bvls(
int key, //key = 0, the subroutine solves the problem from scratch. If key > 0 the routine initializes using the user's guess about which components of x are `active'
int m,
int n,
double[] a, // m by n matrix
double[] b, // m-vector
double[] bl, //n-vector of lower bounds on the components of x.
double[] bu, //n-vector of upper bounds on the components of x.
double[] x, //unknown n-vector
//Working arrays:
double[] w, //dimension n
double[] act, //dimension m*(mm+2). mm=min(m,n).
double[] zz, //dimension m
int[] istate, //dimension n+1.
ref int loopA // number of iterations taken in the main loop, Loop A.
);
// Test code
static void BVTEST()
{
int key=0, n=2, m=3;
double[] a= { 1.0, 2.0, 3.0, 4.0, 5.0 };
double[] b= { 10.0, 20.0, 30.0 };
double[] bl= { 0.0, 1.0 };
double[] bu= { 1.0, 2.0 };
double[] x=new double[n];
double[] w=new double[n];
double[] act=new double[m*Math.Min(m, n)+2];
double[] zz=new double[m];
int[] istate=new int[n+1];
int loopA = 0;
// Call Fortran .dll
bvls(key, m, n, a, b, bl, bu, x, w, act, zz, istate, ref loopA);
}
请记住,数组已经是引用类型(默认值),因此它们不需要ref
关键字。输出值需要像loopA
,而是由值参数传递的需要VALUE
,以避免将它们与属性声明ref
,像key
,m
,n
。您可能需要将其大小固定为act
更大,因为此后我在参数中遇到了一些内存损坏。
此发布应该使您朝正确的方向前进。请记住,始终Cdecl
与FORTRAN .dll一起使用,并始终使用implicit none
声明。x86
与Win32
和一起编译,不要使用AnyCPU
。声明您的出口与ALIAS
服装,以显示出来。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句