public : array<Byte>^ Foo(array<Byte>^ data)
gets dynamic size managed array
but how can I get fixed size managed byte array?
I wanna force C# user to send me 8 byte array; and get 8 bytes back
style:
public : Byte[8] Foo(Byte[8] data)
EDIT:
can any1 explain why its impossbile in safe context?
C# does not allow you to do that. You'll simply have to validate the array's length and maybe throw an exception if the length is not 8.
Also, the type of your function can't be Byte[8]; you'll have to change that to Byte[].
If you want to force exactly 8 bytes... consider sending a long or ulong instead. Old-school, but it works. It also has the advantage of not needing an object (a byte[] is an object) - it is a pure value-type (a primitive, in this case)
You can use a fixed size buffer inside a struct. You'll need it to be in an unsafe block though.
unsafe struct fixedLengthByteArrayWrapper
{
public fixed byte byteArray[8];
}
On the C++ side you'll need to use inline_array to represent this type.
As Marc correctly says, fixed size buffers are no fun to work with. You'll probably find it more convenient to do runtime length checking.
Related
I have a little basic issue.
In C there is no byte type so I defined it as unsigned char to hold buffer to system file I need to read and handle.
My C program now needs to work with C# which has byte built-in type but defined as 'unsigned int'.
Would it cause any issues in casting back and forth between the two systems ?
I think no matter what "word" it is used the underlying storage remains unchanged, right. So doing something like
//C#
//byte[] b=new byte[2];
//b[0]=11;
//b[1]=12;
C
byte b[2];//unsigned char
b[0]=(byte)(11);
b[1]=(byte)(12);
is indifferent among the two.
The C standard has defined int8_t since C99. Use that for an 8 bit type, or uint8_t for the unsigned analogue.
Take care when using such a type in a structure though, there's no guarantee that adjacent members will be contiguous in memory. You'll be fine with arrays though.
As long as the valuetype in C is a 'int'-number, there should be no problem casting this back and forth.
There is one C++ function as below which returns me data in unsigned char**
MyCPPFunc(unsigned char** ppData, int &nSize)
I want to convert it to float array in C#. Problem is that internal representation of data returned by CPP could be char\ushort\uint\RGB etc. If I would use as below,
var srcArray = new byte[nSize];
Marshal.Copy(pCPPData, srcArray, 0, nSize/4);
outDataArray = Array.ConvertAll<byte, float>(srcArray, Convert.ToSingle);
It would convert every four consecutive bytes to float, while data in memory could be of different data type length (could be ushort, uchar, RGB etc.)
How to do this in a best performing manner, considering c++ library do support lots of data types and returns data in memory of that type.(although that is represented by uchar**)
I need something of this sort as below. where dataTypeLen can be 1 for char, 2 for short and so on.
Array.Convert(pCPPData, 0, pFloatArray, dataTypeLen, floatArrLen);
Unsafe code will also suffice.
I dont recall any such intelligent Convert'er in the Marshaller. Except for some bold exceptions like String or StringBuilder or Pointers/Handles itself, the Marshaller does not convert datatypes. It gets some bytes and interpretes them as the format(datatype) you requested and returns the format(datatype) you requested. If you ask it to read SHORT then it will decode as SHORT and return a SHORT. It is "not intelligent enough" to know how to convert CHAR into FLOAT. It's just not the job of Marshaller. And, also, not the job of any standard Converter. They can convert/cast simple types one to each other (like double to decimal), but they will not be able to understand more complex structures like "RGB", or, worse, some RGB* with padding to 32bits or BMP with padding at end of the row!
Unless you take some intelligent converter that understands the exact format you have at input, you have to do it manually. You first need to precisely know what type of data it is (uchar, ushort, RGB, etc) and then receive (i.e. marshal) the array in that precise format (uchar[], ushort[], ..) and only then you will be able to convert the elements to floats on the C# side. If you try reading the bytes "just like that", you might run into endianess problems. Of course, you might not care, depending on your needs.
So, for example: if you know that the pCPPData points to uchar array, then unmarshal it as uchar[]; if you know that the pCPPData points to ushort array, then unmarshal it as ushort[]; rgb? unmarshal it as bytes[] or as ints[], depending on the bitdepth of a single color. Then, take the resulting array, loop over it and convert to a new array of floats. (or, just LINQize with .Cast<float>().ToArray() and forget).
However, looking a bit out of the box, you seem to with with some kind of bitmaps. uchar-8bit grayscale, ushort-16bit grayscale, RGB-blah, I guess.. So why dont you try using some Bitmap processors? I dont precisely recall now, but there are functions and classes in .Net that handle/wrap raw byte arrays as Image/Bitmap objects.
For example, see ie. https://stackoverflow.com/a/16300450/717732 or https://stackoverflow.com/a/9560495/717732 - in the latter note the comments, they suggest that you could even set the scan0 to an unmanaged pointer, so you might completely escape the need of marshalling/copying anything. You might get a Bitmap object what just reads directly from the pointer you got from C++ library - and it would read in the format as specified by the ImageFormat specifier you provided. I have not ever tried this, so I say just "might".
But, of course, that would not give you float[] but Bitmap with pixels. If you really need floats, then you'll have to convert it "manually": branch over format, then read them out as the format specifies, then store them in format you want.
I'm porting some C# decompression code to AS3, and since it's doing some pretty complex stuff, it's using a range of datatypes such as byte and short. The problem is, AS3 doesn't have those datatypes.
For the most part I can use uint to hold these values. However, at some points, I get a line such as:
length[symbol++] = (short)len;
To my understanding, this means that len must be read and assigned to the length array as a short. So I'm wondering, how would I do this in AS3? I'm guessing perhaps to do:
length[symbol++] = len & 0xFF;
But I'm unsure if this would give a proper result.
So basically, my question is this: how do I make sure to keep the the correct number of bytes when doing this sort of stuff in AS3? Maybe I should use ByteArrays instead?
Depending on reason why cast is in C# code you may or may not need to keep cast in AS3 code. If cast is purely to adjust type to type of elements of length array (i.e. there is no loss of precision) than you don't need cast. If len can actually be bigger than 0x7FFF you'll need to perform some cast.
I think ByteArray maybe a reasonable option if you need to handle result similar to C# StreamReader, random access may be harder than necessary.
Note that short is 2 bytes long (synonym for System.Int16) so to convert to it using bit manipulations you need to do & 0xFFFF. Be also very careful if casting between signed and unsigned types...
I'm trying to optimize some code where I have a large number of arrays containing structs of different size, but based on the same interface. In certain cases the structs are larger and hold more data, othertimes they are small structs, and othertimes I would prefer to keep null as a value to save memory.
My first question is. Is it a good idea to do something like this? I've previously had an array of my full data struct, but when testing mixing it up I would virtually be able to save lots of memory. Are there any other downsides?
I've been trying out different things, and it seams to work quite well when making an array of a common interface, but I'm not sure I'm checking the size of the array correctly.
To simplified the example quite a bit. But here I'm adding different structs to an array. But I'm unable to determine the size using the traditional Marshal.SizeOf method. Would it be correct to simply iterate through the collection and count the sizeof for each value in the collection?
IComparable[] myCollection = new IComparable[1000];
myCollection[0] = null;
myCollection[1] = (int)1;
myCollection[2] = "helloo world";
myCollection[3] = long.MaxValue;
System.Runtime.InteropServices.Marshal.SizeOf(myCollection);
The last line will throw this exception:
Type 'System.IComparable[]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
Excuse the long post:
Is this an optimal and usable solution?
How can I determine the size
of my array?
I may be wrong but it looks to me like your IComparable[] array is a managed array? If so then you can use this code to get the length
int arrayLength = myCollection.Length;
If you are doing platform interop between C# and C++ then the answer to your question headline "Can I find the length of an unmanaged array" is no, its not possible. Function signatures with arrays in C++/C tend to follow the following pattern
void doSomeWorkOnArrayUnmanaged(int * myUnmanagedArray, int length)
{
// Do work ...
}
In .NET the array itself is a type which has some basic information, such as its size, its runtime type etc... Therefore we can use this
void DoSomeWorkOnManagedArray(int [] myManagedArray)
{
int length = myManagedArray.Length;
// Do work ...
}
Whenever using platform invoke to interop between C# and C++ you will need to pass the length of the array to the receiving function, as well as pin the array (but that's a different topic).
Does this answer your question? If not, then please can you clarify
Optimality always depends on your requirements. If you really need to store many elements of different classes/structs, your solution is completely viable.
However, I guess your expectations on the data structure might be misleading: Array elements are per definition all of the same size. This is even true in your case: Your array doesn't store the elements themselves but references (pointers) to them. The elements are allocated somewhere on the VM heap. So your data structure actually goes like this: It is an array of 1000 pointers, each pointer pointing to some data. The size of each particular element may of course vary.
This leads to the next question: The size of your array. What are you intending to do with the size? Do you need to know how many bytes to allocate when you serialize your data to some persistent storage? This depends on the serialization format... Or do you need just a rough estimate on how much memory your structure is consuming? In the latter case you need to consider the array itself and the size of each particular element. The array which you gave in your example consumes approximately 1000 times the size of a reference (should be 4 bytes on a 32 bit machine and 8 bytes on a 64 bit machine). To compute the sizes of each element, you can indeed iterate over the array and sum up the size of the particular elements. Please be aware that this is only an estimate: The virtual machine adds some memory management overhead which is hard to determine exactly...
I have a large byte array with mostly 0's but some values that I need to process. If this was C++ or unsafe C# I would use a 32bit pointer and only if the current 32bit were not 0, I would look at the individual bytes. This enables much faster scanning through the all 0 blocks. Unfortunately this must be safe C# :-)
I could use an uint array instead of a byte array and then manipulate the individual bytes but it makes what I'm doing much more messy than I like. I'm looking for something simpler, like the pointer example (I miss pointers sigh)
Thanks!
If the code must be safe, and you don't want to use a larger type and "shift", them you'll have to iterate each byte.
(edit) If the data is sufficiently sparse, you could use a dictionary to store the non-zero values; then finding the non-zeros is trivial (and enormous by sparse arrays become cheap).
I'd follow what this guy said:
Using SSE in c# is it possible?
Basically, write a little bit of C/C++, possibly using SSE, to implement the scanning part efficiently, and call it from C#.
You can access the characters
string.ToCharArray()
Or you can access the raw byte[]
Text.Encoding.UTF8Encoding.GetBytes(stringvalue)
Ultimately, what I think you'd need here is
MemoryStream stream;
stream.Write(...)
then you will be able to directly hadnle the memory's buffer
There is also UnmanagedMemoryStream but I'm not sure whether it'd use unsafe calls inside
You can use the BitConverter class:
byte[] byteArray = GetByteArray(); // or whatever
for (int i = 0; i < b.Length; I += 2)
{
uint x = BitConverter.ToUInt32(byteArray, i);
// do what you want with x
}
Another option is to create a MemoryStream from the byte array, and then use a BinaryReader to read 32-bit values from it.