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”,并添加在在附加依赖项中。
(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)运行!
请求帮助。
写得不清楚的地方我可以在详细说明一下。
之前创建的很多DLL都能够成功使用,但这次由于拟合函数dlevmar_dif有个参数是函数,而且使用了很多指针类型,运行就频频出错,查阅很多资料也无果