我正在使用标签阅读器,我能够连接它并读取一些数据.我的问题是当我尝试读取标签id时,这是一个很大的字符序列.SDK是用C语言编写的,我正在开发一个c#应用程序.short GetIDBuffer(HANDLE hCom, unsigned char* DataFla...
我正在使用标签阅读器,我能够连接它并读取一些数据.我的问题是当我尝试读取标签id时,这是一个很大的字符序列.
SDK是用C语言编写的,我正在开发一个c#应用程序.
short GetIDBuffer(HANDLE hCom, unsigned char* DataFlag, unsigned char * Count,
unsigned char *value, unsigned char* StationNum)
在我的C#应用??程序中:
[DllImport("Reader2.dll",CharSet = CharSet.Ansi)]
public static extern short GetIDBuffer(IntPtr hCom, ref uint DataFlag,
ref uint Count, ref String value, ref uint StationNum);
数据标记,计数,站号主要是小序列,其中uint类型表现良好.但是当谈到价值时,这是一个很大的序列.我尝试了类型字符串,但它抛出了这个异常:
Attempted to read or write protected memory. This is often an
indication that other memory is corrupt.
> [MarshalAs(UnmanagedType.LPWStr)]字符串值
没有解决问题
>计数值正确返回
>我的操作系统是64位:我使用corflags application.exe / 32bit,我能够正确加载DLL.
代码快照:
[DllImport("Reader2.dll")]
public static extern byte OpenReader(ref IntPtr hCom, byte LinkType, string com_port, uint port);
[DllImport("Reader2.dll")]
public static extern short GetIDBuffer(IntPtr hCom, ref byte DataFlag, ref byte Count,**(type)** value , ref byte StationNum);
static void Main(string[] args)
{
byte count = 0, station = 1, flag = 0;
IntPtr hcom = IntPtr.Zero;
OpenReader(ref hcom, 2, "192.168.0.178", 4001);
// valid handle returned from openReader
//
**GetIDBuffer code**
//
解决方法:
您不应该使用corflags application.exe / 32bit.您需要做的就是在project / properties / build中将平台目标设置为x86.
这将起作用(它使用我使用上面给出的相同签名创建的测试本机方法).
第一种方法不需要unsafe关键字,或者要求在“允许不安全代码”设置为true的情况下构建项目.
internal static class NativeMethods
{
[DllImport("Reader2.dll")]
public static extern short GetIDBuffer(
IntPtr hCom, ref byte dataFlag, ref byte count,
byte [] value, ref byte stationNum);
}
static int TestGetIDBuffer()
{
const int arraySize = 255;
byte[] bytes = new byte[arraySize + 1];
byte dataFlag = 0;
byte count = arraySize;
byte status = 0;
int retval = NativeMethods.GetIdBuffer(IntPtr.Zero, ref dataFlag, ref count, bytes, ref status);
Debug.WriteLine(Encoding.ASCII.GetString(bytes));
Debug.WriteLine(dataFlag);
Debug.WriteLine(status);
Debug.WriteLine(count);
Debug.WriteLine(retval);
return retval;
}
这是使用固定字节数组的替代方法.
第二种方法需要unsafe关键字,并且项目是使用“允许不安全代码”设置为true构建的.
internal static class NativeMethods
{
[DllImport("Reader2.dll")]
public static extern unsafe short GetIDBuffer(
IntPtr hCom, ref byte dataFlag, ref byte count,
byte* value, ref byte stationNum);
}
static unsafe int TestGetIDBuffer()
{
const int arraySize = 255;
byte[] bytes = new byte[arraySize + 1];
byte dataFlag = 0;
byte count = arraySize;
byte status = 0;
int retval;
fixed (byte* buffer = bytes)
retval = NativeMethods.GetIdBuffer(
IntPtr.Zero, ref dataFlag, ref count, buffer, ref status);
Debug.WriteLine(Encoding.ASCII.GetString(bytes));
Debug.WriteLine(dataFlag);
Debug.WriteLine(status);
Debug.WriteLine(count);
Debug.WriteLine(retval);
return retval;
}
dataFlag,count和stationNum似乎都是输入/输出字节值.
填充的数据缓冲区是一个字节数组.需要修复此缓冲区,以便在调用本机方法时GC不会移动它.这在第一个示例中隐式完成,在第二个示例中显式完成.
我假设可用的缓冲区大小应该传递给count参数中的方法,并且退出时的这个值将是使用的缓冲区数量.我允许一个额外的字节,以确保如果字节数组需要转换为字符串,则存在空终止字符.
实际上有两种形式的固定语句.在这个MSDN article中提到的一个允许你创建固定大小的数组,如
public fixed byte Bytes [ArraySize];
此MSDN article中的另一个允许您固定变量的位置以获取其地址.
这是我的C测试代码:
extern "C" __declspec(dllexport) unsigned short __stdcall GetIDBuffer(
HANDLE hCom, unsigned char * dataFlag, unsigned char * count,
unsigned char* buffer, unsigned char * status )
{
memset(buffer, 0x1E, *count);
*dataFlag = 0xa1;
*count = 0x13;
*status = 0xfe;
return 0x7531;
}
上面给出的C#代码与我的测试代码之间的唯一区别是,由于我使用了C编译器,因此必须以不同方式指定入口点,例如
[DllImport("PInvokeTestLib.dll", EntryPoint = "_GetIDBuffer@20")]
public static extern unsafe short GetIdBuffer(...
您可以安全地将传递给方法的参数(不包括值数组参数)指定为除byte之外的基本类型,例如int,long等.这是因为1)值在引用中传递,2)x86使用很少 – 字节序字节排序.这导致单个字节被写入传入的四字节int的最低有效字节.
建议使用匹配类型,在这种情况下为byte.
本文标题为:尝试在C#中传递大量字符时尝试读取或写入受保护的内存
基础教程推荐
- C# List实现行转列的通用方案 2022-11-02
- C# windows语音识别与朗读实例 2023-04-27
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- 一个读写csv文件的C#类 2022-11-06
- C#控制台实现飞行棋小游戏 2023-04-22
- unity实现动态排行榜 2023-04-27
- winform把Office转成PDF文件 2023-06-14
- C#类和结构详解 2023-05-30
- C# 调用WebService的方法 2023-03-09
- ZooKeeper的安装及部署教程 2023-01-22