求助:C#调用C++动态库,内嵌结构体指针

加蕃茄的疙瘩汤 2017-11-12 09:02:56
简单叙述一下我的问题:我用C#调用C++编写的动态库,有一个函数的参数是结构体指针,而那个结构体中又嵌套其他的结构体。调用之后发现传递过去的数值不正确,废话不多说,直接上图!希望牛人帮忙解答!
这是C++SDK接口函数

这是提供的C++ Demo结构体定义

这是提供的C++Demo调用SDK

下面是我用C#写的调用接口



现在没有报错信息,只是传过去的数据不对,无法正常调去接口里面的函数。
...全文
807 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
xian_wwq 2017-11-22
  • 打赏
  • 举报
回复
如果是乱码,还得从字符集(CharSet)和对齐方式(Pack)这些基本的设定排查起
  • 打赏
  • 举报
回复
引用 9 楼 Saleayas 的回复:
#define P_CLIENT_MAX_ID_LEN 40

struct P_Client_TIME
{
	DWORD dwYear;
	DWORD dwMonth;
	DWORD dwDay;
	DWORD dwHour;
	DWORD dwMinute;
	DWORD dwSecond;
};
struct P_Client_QueryRecordInfo
{
	char szChannelID[P_CLIENT_MAX_ID_LEN];
	int nSource;
	int nRecordType;
	char szCardInfo[P_CLIENT_MAX_ID_LEN];
	P_Client_TIME sStartTime;
	P_Client_TIME sEndTime;
};

CCALLEDBYCS_API int __stdcall P_Client_QueryRecord(P_Client_QueryRecordInfo *info);
		[StructLayout(LayoutKind.Sequential)]
		public struct P_Client_TIME
		{
			public UInt32 dwYear;
			public UInt32 dwMonth;
			public UInt32 dwDay;
			public UInt32 dwHour;
			public UInt32 dwMinute;
			public UInt32 dwSecond;
		};

		const int P_CLIENT_MAX_ID_LEN = 40;

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
		public struct P_Client_QueryRecordInfo
		{
			[MarshalAs( UnmanagedType.ByValTStr, SizeConst = P_CLIENT_MAX_ID_LEN)]
			public string szChannelID;
			[MarshalAs(UnmanagedType.I4)]
			public int nSource;
			[MarshalAs(UnmanagedType.I4)]
			public int nRecordType;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = P_CLIENT_MAX_ID_LEN)]
			public string szCardInfo;
			public P_Client_TIME sStartTime;
			public P_Client_TIME sEndTime;
		};

		[DllImport("CCalledByCS.dll", EntryPoint = "P_Client_QueryRecord", CallingConvention = CallingConvention.StdCall)]
		public extern static int P_Client_QueryRecord(ref P_Client_QueryRecordInfo info);
我测试了,没有发现问题哦。
------------------------------------ 但是我用的C#传递到C++那边时,他们说接收到的数据是乱码了。
Saleayas 2017-11-18
  • 打赏
  • 举报
回复
#define P_CLIENT_MAX_ID_LEN 40

struct P_Client_TIME
{
	DWORD dwYear;
	DWORD dwMonth;
	DWORD dwDay;
	DWORD dwHour;
	DWORD dwMinute;
	DWORD dwSecond;
};
struct P_Client_QueryRecordInfo
{
	char szChannelID[P_CLIENT_MAX_ID_LEN];
	int nSource;
	int nRecordType;
	char szCardInfo[P_CLIENT_MAX_ID_LEN];
	P_Client_TIME sStartTime;
	P_Client_TIME sEndTime;
};

CCALLEDBYCS_API int __stdcall P_Client_QueryRecord(P_Client_QueryRecordInfo *info);
		[StructLayout(LayoutKind.Sequential)]
		public struct P_Client_TIME
		{
			public UInt32 dwYear;
			public UInt32 dwMonth;
			public UInt32 dwDay;
			public UInt32 dwHour;
			public UInt32 dwMinute;
			public UInt32 dwSecond;
		};

		const int P_CLIENT_MAX_ID_LEN = 40;

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
		public struct P_Client_QueryRecordInfo
		{
			[MarshalAs( UnmanagedType.ByValTStr, SizeConst = P_CLIENT_MAX_ID_LEN)]
			public string szChannelID;
			[MarshalAs(UnmanagedType.I4)]
			public int nSource;
			[MarshalAs(UnmanagedType.I4)]
			public int nRecordType;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = P_CLIENT_MAX_ID_LEN)]
			public string szCardInfo;
			public P_Client_TIME sStartTime;
			public P_Client_TIME sEndTime;
		};

		[DllImport("CCalledByCS.dll", EntryPoint = "P_Client_QueryRecord", CallingConvention = CallingConvention.StdCall)]
		public extern static int P_Client_QueryRecord(ref P_Client_QueryRecordInfo info);
我测试了,没有发现问题哦。
  • 打赏
  • 举报
回复
引用 7 楼 xian_wwq 的回复:
如果对应结构体麻烦 可以试下Mashal方法直接转换,下面是个示例,供参考 其中,TagAttr是个自定义结构体

int size = Marshal.SizeOf(typedef(TagAttr)) ;  
IntPtr attrInput = Mashal.AllocHGlobal(count*size);  
DBPT.GetTagsAttributeWithPtr(nHandle,count,out errors,ids, attrInput);  
for(int i = 0;i< count;i++)  
{  
    IntPtr ptr = (IntPtr)((UInt32)attrInput + i* size);  
    tagsArray[i] = (TagAttr)Mashal.PtrToStructure(ptr,typeof(TagAttr));  
}  
Marshal.FreeHGlobal(attrInput);  
谢谢,周一上班我一定试试,困扰我好长时间了,谢谢您了先
xian_wwq 2017-11-16
  • 打赏
  • 举报
回复
如果对应结构体麻烦 可以试下Mashal方法直接转换,下面是个示例,供参考 其中,TagAttr是个自定义结构体

int size = Marshal.SizeOf(typedef(TagAttr)) ;  
IntPtr attrInput = Mashal.AllocHGlobal(count*size);  
DBPT.GetTagsAttributeWithPtr(nHandle,count,out errors,ids, attrInput);  
for(int i = 0;i< count;i++)  
{  
    IntPtr ptr = (IntPtr)((UInt32)attrInput + i* size);  
    tagsArray[i] = (TagAttr)Mashal.PtrToStructure(ptr,typeof(TagAttr));  
}  
Marshal.FreeHGlobal(attrInput);  
  • 打赏
  • 举报
回复
引用 3 楼 xian_wwq 的回复:
1. char* 对应string,但是需要指定长度 比如 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string LogFilePath; 2. 结构体对应的时候对于字节对齐方式和字符集敏感 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] lz的代码把这些都注释掉了,认为不重要?
------------------------------------------------------------------------------------------------- 首先谢谢您的回答,这种方式我尝试了,还是不可以,数据能过去,但是数据到那边就是乱了的
  • 打赏
  • 举报
回复
引用 2 楼 Saleayas 的回复:
MarshalAs
现在是能传过去数据,但是数据到那边就都乱了,不一定就串到哪里去了,比如年月日,到那边值就互相串了
  • 打赏
  • 举报
回复
还是不行,现在C++那边工程师修改了一下SDK,现在那边能接收到的数据全是不对的,顺序乱了。
xian_wwq 2017-11-13
  • 打赏
  • 举报
回复
1. char* 对应string,但是需要指定长度 比如 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string LogFilePath; 2. 结构体对应的时候对于字节对齐方式和字符集敏感 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] lz的代码把这些都注释掉了,认为不重要?
Saleayas 2017-11-12
  • 打赏
  • 举报
回复
MarshalAs
  • 打赏
  • 举报
回复
有些着急呢,希望牛人能尽快帮忙解答!

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧