c#中调用CERES

因项目中需要使用Ceres进行求解计算,所以有了本文,主要思路就是用C++编写好Ceres求解的函数,然后封装成DLL,最后由C#执行调用从而得到计算结果。

Ceres编译

参考的文章:
Win10 + VS2017 + Ceres配置
Ceres-Solver库使用(一)–windows下安装配置
Ceres Solver 在Windows下安装配置笔记
参考以上几位大佬的文章,应该可以实现Ceres在windows下的配置,本人的环境为Win10 64bit,VS2017,在配置过程中也遇到了一些问题,踩坑记录如下:
在这里插入图片描述
在这里插入图片描述
在配置管理器中的预处理器中添加如下两项:
_CRT_NONSTDC_NO_DEPRECATE
_CRT_SECURE_NO_WARNINGS


在预处理器中添加
GOOGLE_GLOG_DLL_DECL=

在这里插入图片描述
在这里插入图片描述
以上两个错误是在C++编写dll库中会遇到的,在预处理器中添加
GLOG_NO_ABBREVIATED_SEVERITIES
NOMINMAX
按照参考文章中,在vs2017中新建了一个项目编译并运行成功。有些文章中说用CMake编译后,可以用命令行执行helloworld.exe,但本人按这种方法没有成功,没有找到原因。
在这里插入图片描述

C++编写调用Ceres的DLL

.h文件代码,主要是添加extern “C”定义导出函数

class CERESDLL_API CCeresDll {
public:
	CCeresDll(void);
	// TODO: 在此处添加方法。
};

extern "C" CERESDLL_API int nCeresDll;
extern "C" CERESDLL_API int fnCeresDll(void);
extern "C" CERESDLL_API double testCeresDll(void);

.cpp文件

#include "pch.h"
#include "framework.h"
#include "Ceres_Dll.h"
#include <ceres\ceres.h>
#include <glog\logging.h>

using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solver;

struct CostFunctor {
	template <typename T>
	bool operator()(const T* const x, T* residual) const {
		residual[0] = T(10.0) - x[0];
		return true;
	}
};
// 这是导出变量的一个示例
CERESDLL_API int nCeresDll=0;

// 这是导出函数的一个示例。
CERESDLL_API int fnCeresDll(void)
{
    return 0;
}

CERESDLL_API double testCeresDll(void)
{
	google::InitGoogleLogging(new char(123));
	// The variable to solve for with its initial value.
	double initial_x = 5.0;
	double x = initial_x;
	// Build the problem.
	Problem problem;
	// Set up the only cost function (also known as residual). This uses
	// auto-differentiation to obtain the derivative (jacobian).
	CostFunction* cost_function =
		new AutoDiffCostFunction<CostFunctor, 1, 1>(new CostFunctor);
	problem.AddResidualBlock(cost_function, NULL, &x);

	// Run the solver!
	Solver::Options options;
	options.linear_solver_type = ceres::DENSE_QR;
	options.minimizer_progress_to_stdout = true;
	Solver::Summary summary;
	Solve(options, &problem, &summary);
	return x;
}

// 这是已导出类的构造函数。
CCeresDll::CCeresDll()
{
    return;
}

C#调用DLL

新建一个控制台程序,要添加命名空间System.Runtime.InteropServices,然后定义DLL中的函数,代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace CeresDllTest_CSharp
{
    class Program
    {
        [DllImport("CERESDLL.dll")]
        private static extern int fnCeresDll();
        [DllImport("CERESDLL.dll")]
        private static extern double testCeresDll();
        static void Main(string[] args)
        {
            int n = fnCeresDll();
            double value = testCeresDll();
            Console.WriteLine();
        }
    }
}

运行结果如下:

源代码下载链接

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐