目录
C#(.NET)调用C++程序文档...
一、 前言...
二、 通过CLR方式(windows平台)...
三、 通过P/Invoke平台调用方式(linux平台)...
一、前言通过C#(.NET)调用C++程序(.dll/.so)通常有三种方式:①通过CLR方式调用(仅支持windows *** 作系统)。②通过P/Invoke平台调用,即将c++代码编译成独立的动态库(.dll/.so)程序供C#程序加载。③组件调用
本文档只实践了前两种方式,因此只对前两种方式进行说明。示例程序分3层:
- C# 调用层
- C++包装层
- C++ 算法代码层
使用C++包装层封装C++的算法代码,以供C#层直接调用
二、通过CLR方式(windows平台)通过CLR方式,仅支持windows平台:
第三层c++算法代码层无需做特殊处理。
第二层C++包装层,需开启CLR支持,选择C#层所使用的的框架版本,并使用命名空间using namespace System;
以下提供几种参数传递的示例:
①C#传递单个int/float/bool/string等类型至c++:
1.(System::Int32 num) 或 (Int num)传递int类型
(System::Boolean num)传递bool类型
(System:: Single num)传递float类型
2.(System::String^ str)传递字符串类型,(C++封装层函数内部需使用(std::string tmp = msclr::interop::marshal_as
②C#传递数组类型至c++(仅支持一维数组)
如:array<int>^ dim
注:使用CLR进行参数传递时,推荐设置解决方案为X64平台,使用32位时会出现原因未知的参数传递错误,详见demo中的getCoords函数
(在x86下,c++层的内存 *** 作出现了错误)
三、通过P/Invoke平台调用方式(Linux平台)该调用方式C#和C++可以互相分离,C#只需导入C++编译生成的动态库文件
1.参数传递仅支持基本C数据类型,调用c++动态库时,需要加入DllImport,手动导入C++生成的动态库文件(windows为.dll,linux为.so)
2.参数传递详见微软官方文档使用 C++ 互 *** 作(隐式 PInvoke)
数组的传出较为繁琐,传出字符数组(字符串)时可在C#层使用指针IntPtr作为返回值,调用函数string str = Marshal.PtrToStringAnsi(ptr);进行转换。而其他数组在demo中使用循环传递单个数值的方式进行传递。后续优化可简单使用json字符串直接进行数据传递
3.使用visual studio在 linux编译c++ .so文件方法:
①使用visual studio 2019创建Linux c++项目:
在 项目属性-常规-项目默认值 中把配置类型改为动态库(.so)
②配置Linux登录设置、项目目录
远程生成计算机为Linux计算机,远程根目录为该项目在Linux计算机上的项目根目录
生成时调用的是远程Linux计算机上的g++进行编译,而不是windows上的编译环境,所有C++语法须使用g++编译器支持的语法。生成时会同时在上图的“输出目录”和“远程输出相对目录”下生成文件
③配置链接库
有些C++项目需要依赖其他.so文件,如demo中的VTK项目,需要依赖VTK库的.so文件,除了需要配置头文件外,还需要配置链接器中的附加依赖项。与windows项目不同的是,附加依赖项中的.so文件须使用绝对路径,否则会提示找不到.so文件
- Linux运行.net core的C#程序
使用dotnet命令运行,demo中调用的C++ .so动态库文件为GeoModelLibrary.so,需要将该文件及其所依赖的.so文件,拷贝到C#dll的同一目录下,在Linux配置文件中新增该目录。
配置结束以后,需要运行命令ldd GeoModelLibrary.so,检查该so文件的依赖项,确保没有出现not found
若是没有找到依赖文件,确保配置的共享库目录正确生效;若是提示没有找到opengl等文件,确保正确安装Linux的opengl库(yum install mesa*)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)