minpack fortran .dll用于c#

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了minpack fortran .dll用于c#相关的知识,希望对你有一定的参考价值。

我试图在我的c#windows窗体解决方案中包含用FORTRAN编写的minpack,用于解决欠定数学问题的最小二乘解。

我已经读过可以编译minpack fortran子程序,其中有7个(都在单独的文件中)到.dll中,我可以在Visual Studio 2012中添加它作为对我的c#程序的引用。

我一直试图这样做2天没有太多运气。我已经下载了GCC GNU来编译fortran文件。我到目前为止的步骤是:

1)在mingw64env命令提示符中使用语法“gcc -c filename1.f”将fortran文件编译为公共对象文件格式(COFF * .o)文件,用于所有7个文件

2)然后我使用语法“gcc -shared -o mindpack.dll filename1.o filename2.o filename3.o ...”将这些文件一起编译成共享可执行文件。

这会输出一个没有报告错误的.dll文件。

3)但是当我尝试将其添加为我的Windows窗体项目(c#)的引用时,我收到错误消息“无法添加对'* .dll'的引用。请确保该文件可访问,并且它是一个有效的程序集或COM组件。“

4)解决此问题的建议之一是找到文件C: Program Files(x86) Microsoft SDKs Windows v7.0A Bin TlbImp.exe并使用语法“TlbImp.exe minpack.dll”执行它“但这会产生错误”TlbImp:错误T10000:输入文件'C: mingw64 minpack.dll'不是有效的类型库。

任何人都可以指出我正确的方向,因为我只是开始学习c#而且网上的一些解决方案都是头脑文件和DEF文件之类的东西,我不确定这些是否相关。

如果有人可以提出将fortran子程序集合转换为可以从c#调用的单个.dll文件的解决方案,最好使用GCC GNU(或其他一些免费软件),我们将非常感激。

提前致谢。

答案

无法将非托管dll添加为对C#应用程序的引用。 GCC无法轻松为您链接COM对象。

如果dll导出了许多全局函数,那么你应该能够使用Platfrom Invoke(DllImport属性)从C#中调用它们

请查看此article或Google搜索中的任何其他内容。

另一答案

这个答案与问题有点正交,因为它完全避免了Fortran,但考虑到C#和MINPACK搜索结果中问题的普遍存在,值得一提的是open source C/C++ port of MINPACK可用,这可以简化制作可调用内容的过程。净。

要使用这个特定的库,

  1. 下载一个release version of the source code,最近写的是1.6.3。
  2. 打开包含在其中的Visual C ++解决方案cminpack.sln,并构建它以获取库cminpack_dll.dll
  3. cminpack_dll.dll添加到.NET解决方案中,并确保在构建时将其复制到输出目录。
  4. 此时,可以使用P/Invoke调用库。

下面的示例显示了如何将二次函数拟合到给定的数据点集合:

class Program
{
    static void Main()
    {
        // Define some test data by 5i + 3i^2. The plan is to let cminpack figure out
        // the values 5 and 3.
        var data = Enumerable.Range(0, 20)
            .Select(i => 5 * i + 3 * Math.Pow(i, 2))
            .ToList();

        CminpackFuncMn residuals = (p, m, n, x, fvec, iflag) =>
        {
            unsafe
            {
                // Update fvec with the values of the residuals x[0]*i + x[1]*i^2 - data[i].
                var fvecPtr = (double*)fvec;
                var xPtr = (double*)x;
                for (var i = 0; i < m; i++)
                    *(fvecPtr + i) = *xPtr * i + *(xPtr + 1) * Math.Pow(i, 2) - data[i];
            }
            return 0;
        };

        // Define an initial (bad) guess for the value of the parameters x.
        double[] parameters = { 2d, 2d };
        var numParameters = parameters.Length;
        var numResiduals = data.Count;
        var lwa = numResiduals * numParameters + 5 * numParameters + numResiduals;

        // Call cminpack
        var info = lmdif1(
            fcn: residuals,
            p: IntPtr.Zero,
            m: numResiduals,
            n: numParameters,
            x: parameters,
            fvec: new double[numResiduals],
            tol: 0.00001,
            iwa: new int[numParameters],
            wa: new double[lwa],
            lwa: lwa);

        // parameters now contains { 5, 3 }.
        Console.WriteLine($"Return value: {info}, x: {string.Join(", ", parameters)}");
    }

    [DllImport("cminpack_dll.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int lmdif1(CminpackFuncMn fcn, IntPtr p, int m, int n, double[] x,
        double[] fvec, double tol, int[] iwa, double[] wa, int lwa);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int CminpackFuncMn(IntPtr p, int m, int n, IntPtr x, IntPtr fvec, int iflag);
}

在这里,lmdif1CminpackFuncMn的签名可以通过检查cminpack中的relevant header file来推断。

以上是关于minpack fortran .dll用于c#的主要内容,如果未能解决你的问题,请参考以下文章

C-Fortran 字符串互操作性

Fortran与C的混编

通过在 C++ 接口周围创建 C 包装器,在 FORTRAN 中调用 C++ dll 文件 [关闭]

C++ 从 dll 调用 FORTRAN 子例程

Matlab调用Fortran编译的DLL——未完待续

使用 fortran dll 的线程安全 C# 服务