使用C++开发算法(全景拼接、人脸识别、超分辨率重建)/使用C#开发服务端业务逻辑和UI 简介 现工作中作由于 C++ 的 UI(MFC 、QT )开发界面比较难看,定制用户控件复杂且样式一般。而 C# 又不擅长于开发算法逻辑,效率不如 C++。所以现在大部分公司都会选用 C#/C++ 混合编程。
性能分析 使用 C# 做界面要比 C++ 高效的多,但是存在算法逻辑的时候由于性能问题不得不把部分模块交给 C++ 处理,C++ 可以使用高效的栈内存对象(CCalc),而 C# 所有对象只能放在托管堆中。测试 C# 调用 C++ 类库使用托管 方式性能得到了一定程度的提升,但比起单纯的 C++ 项目,还是差了很多;测试 C# 调用 C++ 类库使用 DllImport  Attribute  混合方式由非托管动态链接库 效率与单独运行 C++ 相差无几。
基础代码 .h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #pragma  once #ifdef  TEST_EXPORTS #define  Test_API __declspec(dllexport) #else  #define  Test_API __declspec(dllimport) #endif   #ifdef  __cplusplus # define  CEXTERN extern "C"  #else  # define  CEXTERN #endif  #define  EXPORT_DLL CEXTERN Test_API EXPORT_DLL int  Add (int  a, int  b)  ;EXPORT_DLL char * FilePath (char * filePath)  ;
.cpp 1 2 3 4 5 6 7 8 9 10 11 int  Add (int  a, int  b) 	return  a + b; } char * FilePath (char * filePath) 	char * resurlt; 	resurlt = filePath; 	return  resurlt; } 
.cs 1 2 3 4 5 6 7 8 9 10 11 12 13 private  const  string  dllName = @"Dll.dll" ;[DllImport(dllName, EntryPoint = "Add" , CallingConvention = CallingConvention.Cdecl) ] public  static  extern  int  Add (int  a, int  b[DllImport(dllName, EntryPoint = "FilePath" , CallingConvention = CallingConvention.Cdecl) ] public  static  extern  IntPtr FilePath (IntPtr filePath )static  void  Main (string [] args { 	int  iAdd = Add(8 , 12 ); 	string  strFile = Marshal.PtrToStringAnsi(FilePath(Marshal.StringToHGlobalAnsi(@"1.JPG" ))); } 
注意事项 引用方法乱码 使用 C++ 声明方法会导致引用是乱码,引用名称可以通过 Depends  查询。改为 C 声明后可正常引用方法,建议所有方法使用 C 声明,例如使用 C++ 需要引用方法:”?Add@@YAHHH@Z”,而使用 C 声明只需引用:”Add”。
报错:无法加载 DLL“xxx.dll”: 找不到指定的模块 推荐使用 Depends  工具检测缺少引用类库
报错:调用 Dll “试图加载格式不正确的程序。(异常来自 HRESULT:0x8007000B) 调用64位类库需要把项目改为64位
无法分配内存空间 报错:引发的异常: 0xC0000005: 执行位置 0x0000000000027DD4 时发生访问冲突。
1 2 char * chars = new  char [1024 ];char * chars = (char *)malloc (sizeof (char ) * 1024 );
回调函数 c# 以非动态链接库调用 c++ 后,c++ 以回调函数的方式返回给 c#。
.cs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [UnmanagedFunctionPointer(CallingConvention.Cdecl) ] public  delegate  void  LogCALLBACK (string  log[DllImport(dllName, EntryPoint = "CallbackTest" ) ] public  static  extern  void  CallbackTest (LogCALLBACK log )static  void  Main (string [] args { 	logCALLBACK = Action_logCALLBACK; 	CallbackTest(logCALLBACK); } private  static  void  Action_logCALLBACK (string  log{ 	Console.WriteLine(log); } 
.h 1 2 3 typedef  void (*LogCALLBACK) (char * log) EXPORT_DLL void  CallbackTest (LogCALLBACK logCALLBACK)  ;
.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 void  CallbackTest (LogCALLBACK logCALLBACK) 	for  (size_t  i = 0 ; i < 1000 ; i++) 	{ 		string strLog = "hello" ; 		char * log = new  char [1024 ]; 		strcpy (log, strLog.c_str ()); 		if  (logCALLBACK != NULL ) 		{ 			logCALLBACK (log); 		} 		delete  log; 	} } 
函数中传递结构体与数组 c++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 struct  MyStruct {     int  id;     float  values[10 ]; }; EXPORT_DLL void  ProcessArray (MyStruct* arr)  	arr.id = 1 ; 	for  (int  i = 0 ; i < 10 ; i++) 	{ 		arr.values[i] *= 2.0f ; 	} } 
c# 1 2 3 4 5 6 7 8 9 10 11 12 using  System.Runtime.InteropServices;struct  MyStruct{     public  int  id;     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10) ]     public  float [] values; } [DllImport(dllName, EntryPoint = "ProcessArray" ) ] public  static  extern  void  ProcessArray (ref  MyStruct arr