调试1:C#窗口应用程序与OPENCV C++dll的调用

1.新建窗体应用程序(windowApplication); 2.在解决方案中新建dllProject; 3.配置dllProject:openCV(环境变量,包含目录,库目录,依赖项); 4.配置dllProject:输出目录,设置为windowApplication中应用程序(.exe)同路径下(x64路径下); 5.windowApplication新建类headerSpace,声明类中函数;然后在Form.cs调用类函数,运行

托管/非托管

1.C++内存管理(非托管)

在C/C++中,资源都是需要手动释放的,比如,你new了一个指针,用过之后就需要delete掉,否则就会造成内存泄露。

2.C#内存管理(绝大部分托管)

c#,运行于.net平台上的代码,有自己的内存回收机制,分配的资源一般会自动由平台的垃圾回收器释放,这样的资源就是托管资源;所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存, 但是一些例外的资源,如System.IO.StreamReader等各种流、各种连接所分配的资源,需要显式调用Close()或Dispose()释放,这种资源就叫做非托管资源;

3.C#,C++数据传递

遇到C#与C++传递数据时,就会涉及到托管内存与非托管内存之间的转换 托管内存和非托管内存在c#里面可以互相自由的转化,主要通过Marshal类和GCHandle类,编程时只要注意非托管的内存一定要负责好释放就可以了 举例:C#使用byte传递图像数据到C++

4.其他理解

源代码首先经过预处理器,对头文件以及宏进行解析,然后经过编译器,生成汇编代码,接着,经过汇编,生成机器指令,最后将所有文件连接起来。 这种编译方式的优点在于,最终直接生成了机器码,可以直接被计算机识别和运行,无需任何中间运行环境,但缺点也在于,由于不同平台能够识别的机器码不同,因此程序的跨平台能力较差。 托管/非托管是微软的.net framework中特有的概念,其中,非托管代码也叫本地(native)代码。先将源代码编译成中间代码(MSIL,Microsoft Intermediate Language),然后再由.net中的CLR将中间代码编译成机器代码。

IntPtr

先来看看MSDN上说的:用于表示指针或句柄的平台特定类型。这个其实说出了这样两个事实,IntPtr 可以用来表示指针或句柄、它是一个平台特定类型。对于它的解释,这个哥们写的比较好:It's a class that wraps a pointer that is used when calling Windows API functions. The underlying pointer may be 32 bit or 64 bit, depending on the platform(它是一个类,它封装了调用WindowsAPI函数时使用的指针。根据平台的不同,底层指针可以是32位,也可以是64位).

var

var 是3.5新出的一个定义变量的类型 其实也就是弱化类型的定义 VAR可代替任何类型 编译器会根据上下文来判断你到底是想用什么类型的 至于什么情况下用到VAR 我想就是你无法确定自己将用的是什么类型 就可以使用VAR 类似 OBJECT 但是效率比OBJECT高点。 或者通俗的讲: var可以理解为匿名类型,我们可以认为它是一个声明变量的占位符。它主要用于在声明变量时,无法确定数据类型时使用。 使用var定义变量时有以下四个特点: 1.必须在定义时初始化。也就是必须是var s = “abcd”形式,而不能是如下形式: var s; s = “abcd”; 2.一但初始化完成,就不能再给变量赋与初始化值类型不同的值了。 3.var要求是局部变量。 4.使用var定义变量和object不同,它在效率上和使用强类型方式定义变量完全一样。 

C#传递结构体参数到C++

举例1: (1)C++:定义结构体API与传递函数API; (2)C#:声明同样的结构体,并使用构造函数初始化; (3)C#:调用传递函数 (4)缺陷:若第一个传递的是int类型,其他是double类型,其他的数据在C++中无法正常读取; 参考连接:https://stackoverflow.com/questions/5230147/passing-structure-from-c-sharp-to-c 暂时不考虑bool传递 C++中的代码: 

DllAPI struct DataPassToCPP
{
double passNums;
double passParameter1;
int passParameter2;
int passParameter3;
int passParameter4;
double passParameter5;

};
DllAPI void FaceGenerationDummy(DataPassToCPP m_DataPassToCPP)
{
int x = 0;
}

C#中的代码: 

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SnapRoundingOption
{

public double passNums;
public double passParameter1;
public int passParameter2;
public int passParameter3;
public int passParameter4;
public int passParameter5;

public SnapRoundingOption(double INpassNums, double INpassParameter1, int INpassParameter2, int INpassParameter3, int INpassParameter4, int INpassParameter5)
{

passNums = INpassNums;
passParameter1 = INpassParameter1;
passParameter2 = INpassParameter2;
passParameter3 = INpassParameter3;
passParameter4 = INpassParameter4;
passParameter5 = INpassParameter5;

}
}

[DllImport("imageProcessProject.dll")]
public static extern void FaceGenerationDummy(SnapRoundingOption snapRoundingOption);

调用传递参数: 

FaceGenerationDummy(new SnapRoundingOption(1.2,1.6,2,3,4,5));

举例2:将委托类型转换成非委托类型: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.structuretoptr?redirectedfrom=MSDN&view=netcore-3.1#overloads

常见问题:

1.对象当前正在其他地方使用 

很奇怪的一个做法是定义新的变量int width,来代替bmp.width作为函数的参数传递; 2.外部组件发生异常 

很奇怪的是使用高斯滤波时出现该问题,不使用高斯滤波就不会出现此问题 3.C#不能调用C++的类,怎么办? C++生成的DLL一般只提供函数接口,不能直接用C#调用C++写的类,这样非常不方便 现在使用C#做界面存在一个问题,C#可以调用C++(opencv)写的函数,生成的dll比较方便,但是使用类的dll遇到了困难,网络上给出CLI (托管模式c++),不知道该方法是否可行? 回答:可以,但是太麻烦了,第一:需要新建一个类将C++类做包装,编译成clr,然后才可以被C#调用,第二:C#传递到C++中参数需要调整(C#图片未Bitmap,C++是mat类型需要转换),所以放弃用C#,使用Qt来实现; https://blog.csdn.net/azhexg/article/details/16118921 https://www.cnblogs.com/fourseas/p/4603332.html https://www.cnblogs.com/ly4cn/archive/2006/03/31/363738.html 那么,我就只传递函数出去,每一个类写成一个函数,根据传递参数,来决定使用哪一个函数