You do not need to use corflags application.exe / 32bit +. All you have to do is install the target x86 platform in the project / properties / assembly.
This will work (it’s good that it uses its own test method, which I created with the same signature as above). This first method does not require an unsafe keyword or requires that the project be built with "Allow unsafe code" equal to 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; }
Here's an alternative using a fixed byte array. This second method requires an unsafe keyword, and also that the project is built with "Allow unsafe code" set to 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; }
The data dataFlag, count, and stationNum seem to be byte / output values.
The data buffer is populated with an array of bytes. This buffer needs to be fixed so that the GC does not move it while you call your own method. This is done implicitly in the first example and explicitly in the second.
I assume that the available buffer size should be passed to the method in the count parameter and that this value will be the amount of buffer used when exiting. I allowed an extra byte to provide a null terminating character if the byte array should be converted to a string.
In fact, there are two forms of a fixed operator. One of the MSDN mentioned in this article allows you to create a fixed-size array, as in the open fixed byte Bytes [ArraySize]; Another in this MSDN article allows you to specify the location of a variable for its address.
Here is my C ++ test code:
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; }
The only difference between the above C # code and my test code is that the entry point should be set differently since I used the C ++ compiler, for example.
[DllImport("PInvokeTestLib.dll", EntryPoint = " _GetIDBuffer@20 ")] public static extern unsafe short GetIdBuffer(...
You can safely specify the parameters passed to the method (not including the array of values parameter) as primitive types other than bytes, such as int, long, etc. This is due to the fact that 1) the values are passed by reference and 2) x86 uses the byte order of the low byte. This causes a single byte to be written to the least significant byte of the int byte passed in.
Matching types are recommended, but byte in this case.