求教C#调用VC++6.0的dll在数据转化方面的问题 本帖最后由 Li_Huiyi 于 2010-09-30 11:18:20 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 DWORD 对应 C#的 long 吧 加一个字节对齐试试[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi,Pack=1)] 实在不行,你就一个一个拷贝吧。指针已经得到了,只要拷贝制定大小就行了。int dwSize = ConvertInt(serverInfo);dwServerFlag = ConvertInt(serverInfo); 试了,没用。调用的函数re = JBNV_DLLFuction.JBNV_GetServerInfo(hServer, ref serverInfo);两个参数,第一个参数是上一个函数(同一个dll里面的函数)返回的视频服务器句柄,所以这个参数应该不会有问题。函数返回的结果显示参数不正确,我就判断是第二个参数传的不对。我想可能是对这两个成员的类型转化有问题,到底该怎么转呢?BYTE bServerSerial[48]; //服务器序列号,具有唯一标识功能BYTE byMACAddr[6]; //服务器的物理地址我一开始参照MSDN上这样的一个例子:// 传递到该函数的初始结构包含以下元素:typedef struct _OSVERSIONINFO{ DWORD dwOSVersionInfoSize; DWORD dwMajorVersion; DWORD dwMinorVersion; DWORD dwBuildNumber; DWORD dwPlatformId; TCHAR szCSDVersion[ 128 ]; } OSVERSIONINFO;// 函数原型:BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);// C#中的定义[ StructLayout( LayoutKind.Sequential )] public struct OSVersionInfo2 { public int OSVersionInfoSize; … [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )] public String versionString;}public class LibWrap { [ DllImport( "kernel32" )] public static extern bool GetVersionEx( [In, Out] OSVersionInfo osvi ); [ DllImport( "kernel32", EntryPoint="GetVersionEx" )] public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi ); }// 函数调用:public class App{ public static void Main() { Console.WriteLine( "\nPassing OSVersionInfo as class" ); OSVersionInfo osvi = new OSVersionInfo(); osvi.OSVersionInfoSize = Marshal.SizeOf( osvi ); LibWrap.GetVersionEx( osvi ); Console.WriteLine( "Class size: {0}", osvi.OSVersionInfoSize ); … Console.WriteLine( "\nPassing OSVersionInfo as struct" ); OSVersionInfo2 osvi2 = new OSVersionInfo2(); osvi2.OSVersionInfoSize = Marshal.SizeOf( osvi2 ); LibWrap.GetVersionEx2( ref osvi2 ); Console.WriteLine( "Struct size: {0}", osvi2.OSVersionInfoSize ); … }}我参照它的用法这样写:// 结构定义: [StructLayout(LayoutKind.Sequential)] public struct JBNV_ServerInfo { public uint dwSize; // 结构大小 public uint dwServerFlag; // 服务器类型 public uint dwServerIp; // 服务器IP(整数表示形式) [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string szServerIp; // 服务器IP(字符串表示形式) public UInt16 wServerPort; // 服务器端口 public UInt16 wChannelNum; // 通道数量 public uint dwVersionNum; // 版本 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szServerName; public uint dwServerCPUType; // 当前CPU类型 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 48)] public byte[] bServerSerial; [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 6)] public byte[] byMACAddr; uint dwAlarmInCount; // 告警输入个数 uint dwAlarmOutCount; // 告警输出个数 uint dwSysFlags; // 系统支持的功能 uint dwUserRight; // 当前用户权限 uint dwNetPriviewRight; // 网络观看权限 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string csServerDes; }// 函数声明: [DllImport("JBNVSDK.dll", CharSet = CharSet.Ansi)] public extern static JBNV_ErrorCode JBNV_GetServerInfo(IntPtr hServer, ref JBNV_ServerInfo serverInfo);// 函数调用: JBNV_ServerInfo serverInfo = new JBNV_ServerInfo(); re = JBNV_DLLFuction.JBNV_GetServerInfo(hServer, ref serverInfo);出现一个异常:尝试读取或写入受保护的内存。这通常指示其他内存已损坏。这很奇怪,如果说是byte[]的问题,但是一楼那种写法并没有出现异常,那么只能是string的错误了。求解。 public extern static Int32 JBNV_GetServerInfo(IntPtr hServer, /*ref*/ IntPtr serverInfo);调用:IntPtr serverInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(JBNV_ServerInfo))); re = JBNV_DLLFuction.JBNV_GetServerInfo(hServer, serverInfo); JBNV_ServerInfo info = (JBNV_ServerInfo)Marshal.PtrToStructure(serverInfo, typeof(JBNV_ServerInfo)); Marshal.FreeHGlobal(serverInfo); 问题解决了,不是类型转换的问题,MSDN上写的那种方式是完全正确的。我的问题出在了结构里有一个参数表征数据结构大小的字段,这个字段要赋值后才能传入,否则的话就会出现参数不正确的错误。这个也是看MSDN上的例子突然想起来的,在视频服务器的SDK说明上根本没有提要赋值才能传入,我没有这方面的编程经验,属于自己在粗心了...谢谢大家,结贴! to :jointan您的这个方法我试了,确实可以正确传入,但是可能是因为表示结构大小的字段没有赋值,所以传出来的结果有问题。我还不知道怎么给函数Marshal.AllocHGlobal分配的内存写入值,所以没有测试到底正不正确。我会留心以后会了再来测试一下的。再次谢谢大家。 Win7内核是.net? log4net自定义日志 string 类型转换成int碰到奇怪问题,请大家帮忙解决下 谢谢。 让datagrid单元格不能获得焦点 c# 数组 筛选 重复的值 Net2.0下C#读取任意的配置文件(如:My.config)的问题??? 请问如何在<iframe>中动态加入链接 请教:在C#中如何调出Access中已定义的窗体 c# 快速开发及配置表 食堂就餐仿真:这是一个c++编的程序,我看都看不懂,好象有点问题,帮我看看 节前求一简单正则.........谢谢 求c# windowform 下调用上海移动企信通empp.dll的源码
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi,Pack=1)]
指针已经得到了,只要拷贝制定大小就行了。
int dwSize = ConvertInt(serverInfo);
dwServerFlag = ConvertInt(serverInfo);
试了,没用。
调用的函数
re = JBNV_DLLFuction.JBNV_GetServerInfo(hServer, ref serverInfo);
两个参数,第一个参数是上一个函数(同一个dll里面的函数)返回的视频服务器句柄,所以这个参数应该不会有问题。函数返回的结果显示参数不正确,我就判断是第二个参数传的不对。
我想可能是对这两个成员的类型转化有问题,到底该怎么转呢?
BYTE bServerSerial[48]; //服务器序列号,具有唯一标识功能
BYTE byMACAddr[6]; //服务器的物理地址我一开始参照MSDN上这样的一个例子:// 传递到该函数的初始结构包含以下元素:
typedef struct _OSVERSIONINFO
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
TCHAR szCSDVersion[ 128 ];
} OSVERSIONINFO;
// 函数原型:
BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
// C#中的定义
[ StructLayout( LayoutKind.Sequential )]
public struct OSVersionInfo2
{
public int OSVersionInfoSize;
…
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]
public String versionString;}public class LibWrap
{
[ DllImport( "kernel32" )]
public static extern bool GetVersionEx( [In, Out] OSVersionInfo osvi ); [ DllImport( "kernel32", EntryPoint="GetVersionEx" )]
public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi ); }
// 函数调用:
public class App
{
public static void Main()
{
Console.WriteLine( "\nPassing OSVersionInfo as class" ); OSVersionInfo osvi = new OSVersionInfo();
osvi.OSVersionInfoSize = Marshal.SizeOf( osvi ); LibWrap.GetVersionEx( osvi );
Console.WriteLine( "Class size: {0}", osvi.OSVersionInfoSize );
…
Console.WriteLine( "\nPassing OSVersionInfo as struct" ); OSVersionInfo2 osvi2 = new OSVersionInfo2();
osvi2.OSVersionInfoSize = Marshal.SizeOf( osvi2 ); LibWrap.GetVersionEx2( ref osvi2 ); Console.WriteLine( "Struct size: {0}", osvi2.OSVersionInfoSize );
…
}
}
我参照它的用法这样写:// 结构定义:
[StructLayout(LayoutKind.Sequential)]
public struct JBNV_ServerInfo
{
public uint dwSize; // 结构大小
public uint dwServerFlag; // 服务器类型
public uint dwServerIp; // 服务器IP(整数表示形式)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string szServerIp; // 服务器IP(字符串表示形式)
public UInt16 wServerPort; // 服务器端口
public UInt16 wChannelNum; // 通道数量
public uint dwVersionNum; // 版本
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string szServerName;
public uint dwServerCPUType; // 当前CPU类型
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 48)]
public byte[] bServerSerial;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 6)]
public byte[] byMACAddr;
uint dwAlarmInCount; // 告警输入个数
uint dwAlarmOutCount; // 告警输出个数
uint dwSysFlags; // 系统支持的功能
uint dwUserRight; // 当前用户权限
uint dwNetPriviewRight; // 网络观看权限
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string csServerDes;
}// 函数声明:
[DllImport("JBNVSDK.dll", CharSet = CharSet.Ansi)]
public extern static JBNV_ErrorCode JBNV_GetServerInfo(IntPtr hServer, ref JBNV_ServerInfo serverInfo);
// 函数调用:
JBNV_ServerInfo serverInfo = new JBNV_ServerInfo();
re = JBNV_DLLFuction.JBNV_GetServerInfo(hServer, ref serverInfo);
出现一个异常:尝试读取或写入受保护的内存。这通常指示其他内存已损坏。这很奇怪,如果说是byte[]的问题,但是一楼那种写法并没有出现异常,那么只能是string的错误了。求解。
re = JBNV_DLLFuction.JBNV_GetServerInfo(hServer, serverInfo);
JBNV_ServerInfo info = (JBNV_ServerInfo)Marshal.PtrToStructure(serverInfo, typeof(JBNV_ServerInfo));
Marshal.FreeHGlobal(serverInfo);
我的问题出在了结构里有一个参数表征数据结构大小的字段,这个字段要赋值后才能传入,否则的话就会出现参数不正确的错误。这个也是看MSDN上的例子突然想起来的,在视频服务器的SDK说明上根本没有提要赋值才能传入,我没有这方面的编程经验,属于自己在粗心了...
谢谢大家,结贴!
to :jointan
您的这个方法我试了,确实可以正确传入,但是可能是因为表示结构大小的字段没有赋值,所以传出来的结果有问题。我还不知道怎么给函数Marshal.AllocHGlobal分配的内存写入值,所以没有测试到底正不正确。我会留心以后会了再来测试一下的。再次谢谢大家。