I’m working on a tag reader and i was able to connect it and read some data. My problem is when I attempt to read the tag id which is a large sequence of characters.
The SDK is in C language and I’m developing a c# application.
short GetIDBuffer(HANDLE hCom, unsigned char* DataFlag, unsigned char * Count,
unsigned char *value, unsigned char* StationNum)
In my C# application:
[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);
Dataflag, count, station number are mainly small sequences where a uint type is doing well. But when it comes to value it’s a large sequence. I tried the type string but it’s throwing this exception:
Attempted to read or write protected memory. This is often an
indication that other memory is corrupt.
-
[MarshalAs(UnmanagedType.LPWStr)]string value
didnt solve the problem
-
count value is returned correctly
-
My operating system is 64 bit: i used
corflags application.exe/32bit+and i was able to load the dll correctly.
code snapshot:
[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**
//
You shouldn’t need to use corflags application.exe/32bit+. All you need to do is set the platform target to x86 in project/properties/build.
This will work (well it does using a test native method I created with the same signature as given above).
This first method doesn’t require the unsafe keyword, or require the project to be built with ‘Allow unsafe code’ set to true.
Here’s an alternative using a fixed array of bytes.
This second method requires the unsafe keyword, and also that the project is built with ‘Allow unsafe code’ set to true.
The dataFlag, count and stationNum all seem to be in/out byte values.
The data buffer being filled is an array of byte. This buffer needs to fixed so that the GC won’t move it while you’re calling the native method. This is done implicitly in the first example, and explicitly in the second.
I’m assuming the available buffer size should be passed into the method in the count parameter, and that this value on exit will be the amount of buffer used. I’ve allowed an extra byte to ensure there’s a null terminating character if the array of bytes needs to converted to a string.
There are actually two forms of the fixed statement. One mentioned in this MSDN article allows you to create fixed size array, as in
public fixed byte Bytes [ArraySize];
The other in this MSDN article allow you to pin the location of a variable in order to take it’s address.
Here’s my C++ test code:
The only difference between the C# code given above and my test code is that the entry point has to be specified differently since I used the C++ compiler, e.g.
You can safely specify the parameters passed to the method (not including the value array parameter) as primitive types other than byte, such as int, long etc. This is because 1) the values are passed in reference and 2) x86 uses little-endian byte ordering. This results in the single byte being written to the least significant byte of the four byte int passed in.
It’s advisable to use matching types though, byte in this case.