K
Ken Allen
I have been using C# for some time now, and for the most part I am very
impressed, and prefer using it over C++. There is one area where C#/.Net
seem, at least to me, to be less than desirable compared to C/C++, and
that is in the area of communication with buffer mappings. I know about
interop, and have programmed a significant amount of code this way, but
it is a real pain compared to using C++, unless I am missing something,
which is quite possible.
My current problem domain is using pass-through commands to control a
SCSI device. It does not matter what the device is, as the issues I am
attempting to deal with are generic in nature.
The SCSI command protocol supports commands of various fixed length,
from 6 to 12 bytes. Many of the bytes have individual meaning, some have
per-bit meanings, and in other cases more than one byte are combined to
have meaning. For example, consider the 10-byte READ command, which is
defined as follows:
28 XX LL LL LL LL 00 TL TL 00
Where:
28 - is the 10-byte read command in hex
XX - is a byte where
bits 0:2 are reserved
bit 3 is the FUA bit
bit 4 is the DPO bit
bits 5-7 are the LUN (typically zero)
LL - these four bytes represent the logical block address
TL - these two bytes inidicate the number of sectors to be read
In C++ it is fairly simple, albeit tedious, to define a structure for
each of the different command structures, cast the actual command buffer
address to the appropriate structure pointer, and then fill in the
command buffer with some informative code. In C# the structures can each
be defined, but then one has to marshal the data into the buffer; there
does not seem to be any effective method by which the code can convert
the structure into a byte array, or vice versa.
While the commands can be handled using member functions that take
parameters and convert the information directly into a byte array, that
approach is not so clean for the results of a SCSI command.
Consider the MODE SENSE command, which can return one or more pages of
information. The return buffer is a byte stream that contains special
structures which are optionally present. For example, there is a buffer
header sructure that describes the overall content of the buffer,
followed by the specified number of data pages, which each have a
special header that identifies the actual page content, followed by the
page itself. Again, in C++ we can read the byte(s) that define the
specific page and then cast a structure pointer permitting us to access
the contents of the page in a meaningful manner. In C#, we can read the
individual byte(s) to determine the page type, but must then use interop
to copy the information from the buffer into a structure for reference.
Even worse is when I want to use a MODE SELECT command and pass two or
more pages of information. Creating the information in a structure
object (or a class) and then serializing it into the buffer is a pain c
compared to the methods I can use in C++.
Is there no way to avoid all this use of marshalling code to achieve
structured access to the contents of the data buffers? It seems to me
that the amount of code that I have to write to achieve this in C# is
almost twice what I can get away with in C++, which just seems wrong,
somehow. I know that pointers are not part of the C# landscape, but this
need to convert between a structure/class and a byte stream or array
seems to be something that should be made much easier than it is.
Especially because this is 'unsafe' code and must exist in a separate
assembly from my main code (or at least the compiler errors tell me so).
-ken
impressed, and prefer using it over C++. There is one area where C#/.Net
seem, at least to me, to be less than desirable compared to C/C++, and
that is in the area of communication with buffer mappings. I know about
interop, and have programmed a significant amount of code this way, but
it is a real pain compared to using C++, unless I am missing something,
which is quite possible.
My current problem domain is using pass-through commands to control a
SCSI device. It does not matter what the device is, as the issues I am
attempting to deal with are generic in nature.
The SCSI command protocol supports commands of various fixed length,
from 6 to 12 bytes. Many of the bytes have individual meaning, some have
per-bit meanings, and in other cases more than one byte are combined to
have meaning. For example, consider the 10-byte READ command, which is
defined as follows:
28 XX LL LL LL LL 00 TL TL 00
Where:
28 - is the 10-byte read command in hex
XX - is a byte where
bits 0:2 are reserved
bit 3 is the FUA bit
bit 4 is the DPO bit
bits 5-7 are the LUN (typically zero)
LL - these four bytes represent the logical block address
TL - these two bytes inidicate the number of sectors to be read
In C++ it is fairly simple, albeit tedious, to define a structure for
each of the different command structures, cast the actual command buffer
address to the appropriate structure pointer, and then fill in the
command buffer with some informative code. In C# the structures can each
be defined, but then one has to marshal the data into the buffer; there
does not seem to be any effective method by which the code can convert
the structure into a byte array, or vice versa.
While the commands can be handled using member functions that take
parameters and convert the information directly into a byte array, that
approach is not so clean for the results of a SCSI command.
Consider the MODE SENSE command, which can return one or more pages of
information. The return buffer is a byte stream that contains special
structures which are optionally present. For example, there is a buffer
header sructure that describes the overall content of the buffer,
followed by the specified number of data pages, which each have a
special header that identifies the actual page content, followed by the
page itself. Again, in C++ we can read the byte(s) that define the
specific page and then cast a structure pointer permitting us to access
the contents of the page in a meaningful manner. In C#, we can read the
individual byte(s) to determine the page type, but must then use interop
to copy the information from the buffer into a structure for reference.
Even worse is when I want to use a MODE SELECT command and pass two or
more pages of information. Creating the information in a structure
object (or a class) and then serializing it into the buffer is a pain c
compared to the methods I can use in C++.
Is there no way to avoid all this use of marshalling code to achieve
structured access to the contents of the data buffers? It seems to me
that the amount of code that I have to write to achieve this in C# is
almost twice what I can get away with in C++, which just seems wrong,
somehow. I know that pointers are not part of the C# landscape, but this
need to convert between a structure/class and a byte stream or array
seems to be something that should be made much easier than it is.
Especially because this is 'unsafe' code and must exist in a separate
assembly from my main code (or at least the compiler errors tell me so).
-ken