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

28 篇文章 5 订阅
4 篇文章 0 订阅

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

    /// <summary>
    /// XML序列化某一类型到指定的文件
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="obj"></param>
    /// <param name="type"></param>
    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)
      {
      }
    }
    /// <summary>
    /// 从某一XML文件反序列化到某一类型
    /// </summary>
    /// <param name="filePath">待反序列化的XML文件名称</param>
    /// <param name="type">反序列化出的</param>
    /// <returns></returns>
    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
IntPTRTestStruct 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<Rectangle> rois = new List<Rectangle>();
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();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C#调用 C++ DLL 的步骤如下: 1. 在 C++ 中定义一个 DLL 导出函数,该函数需要使用 extern "C" 声明,并使用 __declspec(dllexport) 修饰符导出。该函数的参数和返回值类型需要与 C# 中的声明一致。 2. 在 C# 中声明 DLLImport 属性,用于指定 C++ DLL 的名称和函数签名。 3. 在 C#调用 C++ DLL 中的函数。 下面是一个简单的示例,演示如何在 C#调用 C++ DLLC++ DLL 代码: ```cpp // example.cpp #include "stdafx.h" extern "C" __declspec(dllexport) int add(int a, int b) { return a + b; } ``` C# 代码: ```csharp using System.Runtime.InteropServices; class Program { [DllImport("example.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int add(int a, int b); static void Main(string[] args) { int result = add(1, 2); System.Console.WriteLine(result); } } ``` 在上面的示例中,我们首先在 C++ DLL 中定义了一个名为 add 的函数,并使用 __declspec(dllexport) 修饰符导出。然后我们在 C#使用 DllImport 属性指定了 example.dll 的名称和 add 函数的签名。最后,我们在 Main 函数中调用了 add 函数,并将结果打印到控制台上。 需要注意的是,在使用 C++ DLL 时,需要注意函数的调用约定。C++ 默认使用的是 __cdecl 调用约定,而 C# 默认使用的是 __stdcall 调用约定。因此,在使用 C++ DLL 时,需要使用 CallingConvention 属性指定函数的调用约定,以免出现调用错误的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值