2023-09-09 14:07:08 来源 : 博客园
(资料图)
C# 的程序引用C++的dll时,首先要保证两者基于的平台一致,比如都是x64,或者都是x86的程序,否者两者之间不能直接调用,然后,要保证两者的数据类型可以相互识别,相互通用。在此重点介绍几个常用的数据转换。C++结构体struct SGP_ANALYTIC_TEMP{ int rule_id; char rule_name[50]; float max_temp; }; C#对应的结构体声明[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]public struct SGP_ANALYTIC_TEMP{ public int rule_id = 0; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] public string rule_name="123"; public float max_temp = 0;//最高温度值}结构体举例2:结构体中嵌套结构体,此时对于结构体数组,也要使用MarshalAs指定类型,并分配内存
C++结构体struct SGP_GENERAL_INFO{ int range_num;//测温范围数量 SGP_RANGE range[3];//测温范围 char vl_rtsp_url[50];//可见光主码流rtsp地址};C++ 函数类型 int SGP_GetGeneralInfo(SGP_HANDLE handle, SGP_GENERAL_INFO *output);C# 对应的结构体[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]public struct SGP_GENERAL_INFO{ public int range_num ;//测温范围数量 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public SGP_RANGE[] range;//测温范围 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] public string vl_sub_rtsp_url;//可见光辅码流rtsp地址}C# 函数类型[DllImport(sdkPath, EntryPoint = "SGP_GetGeneralInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int SGP_GetGeneralInfo(IntPtr handle, ref SGP_GENERAL_INFO output);遇到的问题问题1 :在引入DLL中的方法时,有时会出现以下错误报告:“在使用托管代码调用非托管代码时,发生“对 PInvoke 函数的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。解决方法:在DllImport时添加 CallingConvention = CallingConvention.Cdecl 即调用方清理堆栈,注意,当调用的C++dll还依赖其他dll时,需要把所调用的dll文件都放在一起,否则会抛出 System.DllNotFoundException的异常问题2:解决方法:主要是由于Dll编译的平台和调用它的工程的平台不一致导致的,可都统一打到X64平台下编译
标签: