C#调用C++DLL的问题

C#调用C++动态链接库的问题
最近想要使用levmar.lib库(C++编写的)中的函数进行曲线拟合,先给出这个库中的函数:

extern int dlevmar_dif(
      void (*func)(double *p, double *hx, int m, int n, void *adata),
      double *p, double *x, int m, int n, int itmax, double *opts,
      double *info, double *work, double *covar, void *adata);

图 1 曲线拟合函数
其中,有个参数为函数!
接下来按照创建C++动态链接库的步骤一步步进行:
(1) 在动态链接库项目中添加头文件声明导出函数

#pragma once
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
/*****************包含文件*********************/
#include"levmar.h"
#include"pch.h"

/*****************函数声明*********************/
extern "C" MATHLIBRARY_API double dlevmar_dif_CS(double* p, double* x, int m, int n, int itmax, double opts,
    double* info, double work, double covar, double* adata, int location);


(2) 添加源文件定义导出函数(ros函数不是输出函数,是为了让dlevmar_dif函数使用而编写的)

/*****************包含文件*********************/
#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier
#include <utility>//包含标准库文件
#include <limits.h>//包含标准库文件
#include "LMForCSharp.h"//包含用户自定义头文件
#include <stdio.h>//包含标准库文件

/*****************非输出函数函数定义*********************/
void ros(double* p, double* x, int m, int n, void* data)//x代表应力,data代表应变
{
    double* data1;
    data1 = (double*)(data);
    register int i;
    for (i = 0; i < n; i++)
    {
        if (m == 2)
        {
            x[i] = (2 * p[0] / p[1]) * (pow(data1[i], (p[1] - 1)) - pow(data1[i], (-0.5 * p[1] - 1)));
        }
        else if (m == 4)
        {
            x[i] = (2 * p[0] / p[1]) * (pow(data1[i], (p[1] - 1)) - pow(data1[i], (-0.5 * p[1] - 1))) +
                (2 * p[2] / p[3]) * (pow(data1[i], (p[3] - 1)) - pow(data1[i], (-0.5 * p[3] - 1)));
        }
        else if (m == 6)
        {
            x[i] = (2 * p[0] / p[1]) * (pow(data1[i], (p[1] - 1)) - pow(data1[i], (-0.5 * p[1] - 1))) +
                (2 * p[2] / p[3]) * (pow(data1[i], (p[3] - 1)) - pow(data1[i], (-0.5 * p[3] - 1))) +
                (2 * p[4] / p[5]) * (pow(data1[i], (p[5] - 1)) - pow(data1[i], (-0.5 * p[5] - 1)));
        }
    }
}


/*****************输出函数函数定义*********************/
double dlevmar_dif_CS(double* p, double* x, int m, int n, int itmax, double opts,
    double* info, double work, double covar, double* adata, int location)
{
    //使用levmar.lib库中的函数
    int ret = dlevmar_dif(ros, p, x, m, n, itmax, &opts, info, &work, &covar, adata);
    //返回拟合参数
    return p[location];
}



(3)在项目属性中包含“levmar.h”和“levmar.lib、lapack.lib、blas.lib、f2c.lib、tmglib.lib、levmar.lib”,并添加在在附加依赖项中。

img

img

(4)刚才说到levmar库中的函数,有个参数为函数,我是直接在动态链接库项目的源文件中定义的,直接让拟合函数dlevmar_dif来使用,如上面的代码。
(5)所有工作都做好之后,就可以生成DLL了。
(6)接下来说明一下C#调用的情况
首先,把DLL放到启动项目文件夹下就不多说了,直接上代码:

        [DllImport(@"\LMForCSharp.dll", CallingConvention = CallingConvention.Cdecl)]
        //声明动态链接库中的导出函数  
        public static extern double dlevmar_dif_CS(double[] p,
        double[] x, int m, int n, int itmax,  double opts, double[] info,  double work,  double covar, double[] adata, int location);

(7)导入动态链接库也声明导出函数之后,给出使用的代码:

        private void button1_Click(object sender, EventArgs e)
        {
            int m = 2;
            int n = 7;
        int itmax = 10000;
        double work = 0;
        double covar = 0;
        double[] info = new double[10];
        double[] p = new double[m];
        double opts = 0;
        for (int i = 0; i < m; i++)
        {
            p[i] = 0.1;
        }
            /*********************************************应变*********************************************/
            double[] adata = { 1, 1.5, 2, 2.5, 3, 3.5, 4 };
            /*********************************************应力*********************************************/
            double[] x = { 0, 1.1328, 2.2221, 3.4706, 4.9168, 6.5691, 8.4280 };
            /*******************************调用函数*******************************/
            int location = 1;
            double Rp = dlevmar_dif_CS(p, x, m, n, itmax, opts, info,  work,  covar, adata, location);
       }

(8)运行!

img


请求帮助。
写得不清楚的地方我可以在详细说明一下。
之前创建的很多DLL都能够成功使用,但这次由于拟合函数dlevmar_dif有个参数是函数,而且使用了很多指针类型,运行就频频出错,查阅很多资料也无果

看不清楚你怎么给指针变量传值的

可以考虑使用C++CLI/CLR来进行转换。方便调试问题出处。