byte[] to byte* in C# - c#

I created 2 programs - in C# and C++, both invoke native methods from C dll. C++ works fine, because there are the same data types, C# doesn't work.
And native function parameter is unsigned char*. I tried byte[] in C#, it didn't work, then I tried:
fixed(byte* ptr = byte_array) {
native_function(ptr, (uint)byte_array.Length);
}
It also doesn't work. Is it correct to convert byte array to byte* in such way? Is it correct to use byte in C# as unsigned char in C?
EDIT:
This stuff returns the wrong result:
byte[] byte_array = Encoding.UTF8.GetBytes(source_string);
nativeMethod(byte_array, (uint)byte_array.Length);
This stuff also returns the wrong result:
byte* ptr;
ptr = (byte*)Marshal.AllocHGlobal((int)byte_array.Length);
Marshal.Copy(byte_array, 0, (IntPtr)ptr, byte_array.Length);

unsafe class Test
{
public byte* PointerData(byte* data, int length)
{
byte[] safe = new byte[length];
for (int i = 0; i < length; i++)
safe[i] = data[i];
fixed (byte* converted = safe)
{
// This will update the safe and converted arrays.
for (int i = 0; i < length; i++)
converted[i]++;
return converted;
}
}
}
You also need to set the "use unsafe code" checkbox in the build properties.

You have to marshal the byte[] :
[DllImport("YourNativeDLL.dll")]
public static extern void native_function
(
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
byte[] data,
int count // Recommended
);

You could allocate an unmanaged array and use Marshal.Copy to copy the contents of the managed byte[] array to an unmanaged unsigned char* array. Note that unmanaged resources must be cleaned up manually.

Related

correct marshalling of c++ structure in c#

I have this structure in C++ that I need to be converted to C#, so I can create this structure from a byte[].
struct TRANS_RECORD_DATA {
int size, code;
int ThrowItemCount;
int ItemCount;
int ItemSubStart;
int DataSize;
BYTE Data[sizeof(sRECORD_ITEM) * 200]; // sizeof(sRECORD_ITEM) = 548
};
The C# version:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TRANS_RECORD_DATA {
public int size, code;
public int ThrowItemCount;
public int ItemCount;
public int ItemSubStart;
public int DataSize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 548*200)]
public byte[] Data;
};
I am using this generic function to give me the structure from the byte array:
T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
T stuff = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof (T));
handle.Free();
return stuff;
}
But it is giving me:
AccessViolation Exception.
I belive I know why but I don't know how to solve it. The byte[] I have, that needs to be mapped into the struct, does not always have the Data member with size of 548*200. This number is a maximum. But seems that that GenericMethod I use, always try to create the struct with that Data always 548*200, and then it will obviously throw an AccessViolation because the data to be mapped has ended already.
For example this code:
var bytes = new byte[26];
var structure = ByteArrayToStructure<TRANS_RECORD_DATA>(bytes);
Should return a TRANS_RECORD_DATA with all those int members with 0 value, and finally that byte[] Data would have only the remaining two bytes. (26 - 24 = 2). But it seems that it tries to create the full 548*200 byte[] all the time, and then cause the access violation.
Is there a way to solve this ?
So as you explaining it, regardless of C definition for Data array being 200*548 bytes long, it is not actually fully allocated or filled by an external unmanaged code you call.
this way your only workaround is NOT to define Data in your C# struct definition:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TRANS_RECORD_DATA {
public int size, code;
public int ThrowItemCount;
public int ItemCount;
public int ItemSubStart;
public int DataSize;
};
and after reading DataSize re-interpret remainder of the byte array as that data structure.
you can still use series of calls to Marshal.PtrToStructure:
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
TRANS_RECORD_DATA stuff = (TRANS_RECORD_DATA) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof (TRANS_RECORD_DATA));
var items = new List<sRECORD_ITEM>(stuff.ItemCount);
for (int i = 0; i < stuff.ItemCount; ++i)
{
var ptr = handle.AddrOfPinnedObject().Add(i*548)
sRECORD_ITEM item = (sRECORD_ITEM)Marshal.PtrToStructure(ptr,typeof(sRECORD_ITEM));
}
I am pretty sure this should do the trick.

How to typecast data pointed by void pointer to a fixed size int array in C#?

This is a similar to the following SO question:
cast-void-pointer-to-integer-array
c-pointers-pointing-to-an-array-of-fixed-size
However, the difference is that I want to achieve this in C# using 'unsafe' feature through which we can use pointers.
e.g.
Following code works in C:
int (*arr)[10] = (int (*)[10]) ptr;
where 'ptr' is void pointer. How can be this achieved in C#?
You can simply cast it to an int* pointer.. hoping for the best.. obviously:
// unsafe {}
var a = stackalloc int[5];
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
var v = (void*) a; // cast to void as example
for (var i = 0; i < 5; i++)
Console.WriteLine((*(int*)v)++); // back to int - 1, 2, 3, 4, 5
That said.. you will have to be vary careful with bounds checking. AFAIK there is no direct translation that allows for bounds.
I'm not entirely sure that this is what you're looking for, but one example would be like this:
int[] items = new int[10];
unsafe
{
fixed ( int* pInt = &items[0] )
{
// At this point you can pass the pointer to other functions
// or read/write memory using it.
*pInt = 5;
}
}
When taking the address of an array, you have to take the address of the first item in the array - hence &items[0] in the example above.
If you receive the pointer as a void* function parameter, you have to cast it inside the function:
public static unsafe void F ( void* pMem )
{
int* pInt = (int*) pMem;
// Omitted checking the pointer here, etc. This is something
// you'd have to do in a real program.
*pInt = 1;
}
If you receive a void* from an external source, you'll have to somehow know how many bytes (or ints, etc.) are safe to access through the pointer. The data may be delimited by a special value (like a terminating 0 or something else) or you'd need a count or bytes / elements to safely access memory through the pointer.
Update
Here's an example of calling an unmanaged function implemented in C:
// Function declaration in C
#define EXPORTFUNC __declspec(dllexport)
#define MYDLLAPI __declspec(nothrow) WINAPI
EXPORTFUNC int MYDLLAPI MyFunc1 ( byte* pData, int nDataByteCount );
// Import function in C#
[DllImport ( "My.dll" )]
private static extern int MyFunc1 ( byte* pData, int nDataByteCount );
// Call function with data (in unsafe class / method)
byte[] byData = GetData ( ... ); // returns byte array with data
fixed ( byte* pData = byData )
{
int nResult = MyFunc1 ( pData, byData.Length );
...
}
MSDN has more examples on various pointer operations. Also, here's another article about marshaling arrays.

C# - Convert unsafe byte* to byte[]

I have an unsafe byte* pointing to a native byte array of known length. How can I convert it to byte[]?
An unsafe sbyte* pointing to a zero-terminated native string can be converted to a C# string easily, because there is a conversion constructor for this purpose, but I can't find a simple way to convert byte* to byte[].
If ptr is your unsafe pointer, and the array has length len, you can use Marshal.Copy like this:
byte[] arr = new byte[len];
Marshal.Copy((IntPtr)ptr, arr, 0, len);
But I do wonder how you came by an unsafe pointer to native memory. Do you really need unsafe here, or can you solve the problem by using IntPtr instead of an unsafe pointer? And if so then there's probably no need for unsafe code at all.
The Marshal class could help you.
byte[] bytes = new byte[length];
for(int i = 0; i < length; ++i)
bytes[i] = Marshal.ReadByte(yourPtr, i);
I think you might use Marshal.Copy too.

iterating over memory allocated with Marshal.AllocHGlobal()

I have a 3rd party C library which one of its exported method's is as follows:
#define MAX_INDEX 8
int GetStuff(IN char* index[MAX_INDEX], OUT char* buf, IN size_t size);
The first argument is populated with pointers into the buf argument where specific strings are stored. The size indicates how long each string is expected to be in the buf buffer. My C# P/Invoke method for this currently looks like this:
[DllImport("Path/To/Dll", CharSet = CharSet.Ansi)]
private static extern int GetStuff(IntPtr indecies, IntPtr buf, Int32 size);
The C# P/Invoke method is private because I'm wrapping it's functionality in a public "getter" method which handles the allocation/deallocation of memory for the caller. When I use this method in C++, iterating is quite simple actually. I simply do something like:
char* pIndecies[MAX_INDEX];
char* pBuffer = new char[MAX_INDEX * (256 + 1)]; // +1 for terminating NULL
GetStuff(pIndecies, pBuffer, 256);
// iterate over the items
for(int i(0); i < MAX_INDEX; i++) {
if(pIndecies[i]) {
std::cout << "String for index: " << i << " " << pIndecies[i] << std::endl;
}
}
Because of how these are used in C++, I decided I should probably use IntPtr objects and just allocate the memory that I'll need from the heap, call into the native code, and iterate over it the way I would in C++. Then I remembered that chars in C# are unicode characters and not ASCII characters. Would iteration in C# work the same even if I placed the iteration in an unsafe code block? My first thought was to do the following:
IntPtr pIndecies = Marshal.AllocHGlobal(MAX_INDEX * 4); // the size of a 32-pointer
IntPtr pBuffer = Marshal.AllocHGlobal(MAX_INDEX * (256 + 1)); // should be the same
NativeMethods.GetStuff(pIndecies, pBuffer, 256);
unsafe {
char* pCStrings = (char*)pIndecies.ToPointer();
for(int i = 0; i < MAX_INDEX; i++) {
if(pCStrings[i])
string s = pCStrings[i];
}
}
My question then is, "How should I iterate over what this native code method returns?" Is this the right way to marshal to this function? Should I use a StringBuilder object for the second argument? One constraining problem is that the first argument is a 1:1 mapping of a structure behind the GetStuff() method. The value of each index is crucial for understanding what you're looking at in the second buffer argument.
I appreciate any suggestions.
Thanks,
Andy
I think you are on the right track, but I'd do it without using unsafe code. Like this:
[DllImport("Path/To/Dll", CharSet = CharSet.Ansi)]
private static extern int GetStuff(IntPtr[] index, IntPtr buf, Int32 size);
....
IntPtr[] index = new IntPtr[MAX_INDEX];
IntPtr pBuffer = Marshal.AllocHGlobal(MAX_INDEX * 256 + 1);
try
{
int res = NativeMethods.GetStuff(index, pBuffer, 256);
// check res for errors?
foreach (IntPtr item in index)
{
if (item != IntPtr.Zero)
string s = Marshal.PtrToStrAnsi(item);
}
}
finally
{
Marshal.FreeHGlobal(pBuffer);
}
This is a pretty direct translation of your C++ version.

Getting Array of struct from IntPtr

I have some struct like this
struct MyStruct
{
public int field1;
public int field2;
public int field3;
}
and I have pointer to array of this struct.
So, I need to get array from this pointer.
I'm tried to using Marshal.PtrToStructure, but i had memory reading error.
This is my methode:
public MyStruct[] GetArrayOfStruct(IntPtr pointerToStruct, int length)
{
var sizeInBytes = Marshal.SizeOf(typeof(TCnt));
MyStruct[] output = new MyStruct[length];
for (int i = 0; i < length; i++)
{
IntPtr p = new IntPtr((pointerToStruct.ToInt32() + i * sizeInBytes));
output[i] = (MyStruct)System.Runtime.InteropServices.Marshal.PtrToStructure(p, typeof(MyStruct));
}
return output;
}
So, what am i doing wrong ?
This function worked for me, assuming that the size of the struct is fixed:
public static void MarshalUnmananagedArray2Struct<T>(IntPtr unmanagedArray, int length, out T[] mangagedArray)
{
var size = Marshal.SizeOf(typeof(T));
mangagedArray = new T[length];
for (int i = 0; i < length; i++)
{
IntPtr ins = new IntPtr(unmanagedArray.ToInt64() + i * size);
mangagedArray[i] = Marshal.PtrToStructure<T>(ins);
}
}
Two problems. You use TCnt instead of MyStruct in the Marshal.SizeOf() call. Your IntPtr arithmetic cannot work on a 64-bit machine, you must use IntPtr.ToInt64() or cast to (long).
Just getting the wrong IntPtr or length is certainly a possibility too of course. Use Debug + Windows + Memory + Memory 1 and put "pointerToStruct" in the Address box for basic verification.
Structs in C and C# are not the same thing. One of the differences is that in C# you have to explicitly demand that your struct should be sequentially laid out. If you didn't write
[StructLayout(LayoutKind.Sequential)] or [StructLayout(LayoutKind.Explicit)] attribute to your structure I don't believe that you can manage it in this way. Microsoft states that PtrToStructure is to be used to convert structures from unmanaged to managed memory
You should test if adding this attributes to your struct helps, If it doesn't yet help try allocating memory with Marshal.AllocHGlobal(IntPtr) and use Marshal.Copy to init your structure and then try using PtrToStructure. If this works then you can't use PtrToStructure with managed memory

Categories