C#编程笔记以及C#调用C++ DLL注意事项

总目录

  • UI相关
    • 如何在PictureBox中实现选择框功能
    • C#进度条实现
    • C#实现复杂XML的序列化与反序列化
  • C#调用C++ DLL
    • 对 PInvoke 函数“Demo!Demo.MyImgCSharp::CalcAllEigens”的调用导致堆栈不对称。
    • 自定义结构体数组传递
    • 函数声明中C++类型与C#类型对应关系
    • C#用指针取结构体数组中内容
    • C#中ref与out区别
  • 图像处理
    • 新的Emgucv使用中常用函数总结
    • EmguCV学习——简单使用
    • cv::Scalar

UI相关

如何在PictureBox中实现选择框功能

https://bbs.csdn.net/topics/390658401?depth_1-utm_source=distribute.pc_relevant.none-task-discussion_topic-BlogCommendFromBaidu-3&utm_source=distribute.pc_relevant.none-task-discussion_topic-BlogCommendFromBaidu-3

C#进度条实现

https://blog.csdn.net/lyxzjq918/article/details/49149795?locationNum=2&fps=1

C#实现复杂XML的序列化与反序列化

https://www.cnblogs.com/rainbow70626/p/4886717.html

    /// 
    /// XML序列化某一类型到指定的文件
    /// 
    /// 
    /// 
    /// 
    public static void SerializeToXml<T>(string filePath, T obj)
    {
      try
      {
        using (System.IO.StreamWriter writer = new System.IO.StreamWriter(filePath))
        {
          System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
          xs.Serialize(writer, obj);
        }
      }
      catch (Exception ex)
      {
      }
    }
    /// 
    /// 从某一XML文件反序列化到某一类型
    /// 
    /// 待反序列化的XML文件名称
    /// 反序列化出的
    /// 
    public static T DeserializeFromXml<T>(string filePath)
    {
      try
      {
        if (!System.IO.File.Exists(filePath))
          throw new ArgumentNullException(filePath + " not Exists");
 
        using (System.IO.StreamReader reader = new System.IO.StreamReader(filePath))
        {
          System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
          T ret = (T)xs.Deserialize(reader);
          return ret;
        }
      }
      catch (Exception ex)
      {
        return default(T);
      }
    }
  }

C#调用C++ DLL

对 PInvoke 函数“Demo!Demo.MyImgCSharp::CalcAllEigens”的调用导致堆栈不对称。

具体问题:对 PInvoke 函数“Demo!Demo.MyImgCSharp::CalcAllEigens”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。
解决办法:C++定义的导出函数如下:
#ifndef DLLOUTAPI
#define DLLOUTAPI extern “C” __declspec(dllexport)
#else
#define DLLOUTAPI extern “C” __declspec(dllimport)
#endif
在C#端调用时添加声明
[DllImport(“MyImg.dll”,CallingConvention = CallingConvention.Cdecl)]

自定义结构体数组传递

C++中结构体定义:

typedef struct // 平面
{
  double time; 
  float normal[3];
  float center[3]; 
} plane;

C++中方法声明:

public void GetPlanes(plane *planes, int size);

C#中结构体声明:注意数组大小的声明方式。

[StructLayout(LayoutKind.Sequential)]
public struct GPlane
{
  public double timestamp;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  public float[] normal;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  public float[] center;
}

C#中方法声明:注意[In, Out]的使用表明传进来的数组会被修改。

[DllImport(LibFileName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern bool Pvr_getAirGlassPlanes([In, Out]GPlane[] plane, int size);

C#中调用该方法:

int size = 2;

GPlane[] plane = new GPlane[size];

Pvr_getAirGlassPlanes(plane, size);

原文链接:https://blog.csdn.net/fenggewan/article/details/88409551

函数声明中C++类型与C#类型对应关系

C++ C# 备注
char * string
指针 IntPTR
自定义结构体指针
TestStruct * struts
IntPTR TestStruct stTest = new TestStruct ();
IntPtr structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(stTest));
func(structPtr);
自定义结构体数组
TestStruct * struts
[In, Out]TestStruct [] struts [In, Out]代表传进来,会被修改后再传出去。C#端举例:
TestStruct [] structArray = new TestStruct [3];
func(structArray);
自定义结构体数组
const TestStruct * struts
TestStruct[] struts 只需要传进来C#端举例:
TestStruct [] structArray = new TestStruct [3];
func(structArray);
自定义结构体数组
TestStruct * struts
ref TestStruct struts 先传进来再被修改后传出去 C#端举例:
TestStruct [] structArray = new TestStruct [3];
func(ref structArray[0]);
常用结构体数组
const cv::Rect * rois
ref Rectangle rois 只需要传进来
所需名称空间 using System.Drawing;
C#端举例:
List rois = new List();
func(ref rois.ToArray()[0]); // 先转为数组,然后再传入数组的首地址
也可以参考上面的方法,直接用数组而不是List
OpenCV图像
func(const uchar* srcImgData,const int rows,const int cols)
func(IntPtr src, int rows, int cols) C#端调用举例:
Mat src= CvInvoke.Imread(path, ImreadModes.Grayscale);
func(src.DataPointer, src.Height, src.Width)
  1. func()指调用函数接口名称。
  2. 注意类型

C#用指针取结构体数组中内容

[DllImport("MyDll.dll")]
public static extern bool func(IntPtr structPtr);

//此处省略中间细节,显示如何调用
int count = 6;
int size = Marshal.SizeOf(typeof(TestStruct));
IntPtr structPtr = Marshal.AllocHGlobal(size * count);
TestStruct[] TestStructs = new TestStruct[count];
if (func(structPtr))
{
    MessageBox.Show("Fail");
    return;
}
for (int index = 0; index < count; index++)
{
    // 两种方法都可以,推荐下面这一种,防止在64位系统中超出上限
    // IntPtr ptr = (IntPtr)((UInt32)structPtr + index * size);
    IntPtr ptr = (IntPtr)(structPtr.ToInt64() + index * size);   // 推荐此种
    
    TestStructs[index] = (TestStruct)Marshal.PtrToStructure(ptr, typeof(TestStruct));
}

Marshal.FreeHGlobal(structPtr);

C#中ref与out区别

ref: 既进且出:在调用前,实参必须赋初始值。
out: 只出不进:在调用前,实参可以不赋初始值。
https://www.cnblogs.com/bedfly/p/12127435.html
https://www.cnblogs.com/QingYiShouJiuRen/p/11353896.html

图像处理

新的Emgucv使用中常用函数总结

https://www.cnblogs.com/motao9527/p/10220445.html

EmguCV学习——简单使用

https://www.cnblogs.com/jixin/p/4727505.html改变

cv::Scalar

C++:
cv::Scalar borderValue = cv::Scalar()

C#:
MCvScalar borderValue = new Emgu.CV.Structure.MCvScalar();

你可能感兴趣的:(C#,C/C++,OpenCV)