C# - Converting String array to sbyte** (String[] to sbyte**) - c#

XFunction is a CLI to managed C++ code (wrapper).
I want to use XFunction(int,sbyte**) in my C# Project and convert String array to sbyte**.
sbyte[][] sbytes = new sbyte[7][];
for (int argCounter = 0; argCounter < 7 ; argCounter++)
{
//get the byte array
byte[] bytes = Encoding.ASCII.GetBytes(argument[argCounter]);
//convert it to sbyte array
sbytes[argCounter] = new sbyte[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
sbytes[argCounter][i] = (sbyte)bytes[i];
}
when I calling:
XFunction(7,sbytes);
and buid, generate this error:
The best overloaded method match for 'XFunction(int, sbyte**)' has
some invalid arguments Argument 2: cannot convert from 'sbyte[][]'
to 'sbyte**'
How can I fixed this error???

You need to use fixed to get pointer to your array and to prevent garbage collection from relocating your variable.
You may want to do something like this:
public static unsafe void CallXFunction(int a, sbyte[][] array)
{
var pointerArray = new sbyte*[array.Length];
// Recursive fixing so that whole array get's pinned at same time
// (never use fixed pointer outside of fixed{} statement)
Action<int> fixArray = null;
fixArray = (pos) =>
{
fixed (sbyte* ptr = array[pos])
{
pointerArray[pos] = ptr;
if (pos <= (array.Length - 2))
{
fixArray(pos + 1);
}
else
{
fixed (sbyte** pointer = pointerArray)
{
XFunction(a, pointer);
}
}
}
};
fixArray(0);
}

it solved by:
sbyte[][] sbytes = new sbyte[6][];
for (int argCounter = 0; argCounter < 6 ; argCounter++)
{
get the byte array
byte[] bytes = Encoding.ASCII.GetBytes(argument[argCounter]);
convert it to sbyte array1
sbytes[argCounter] = new sbyte[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
sbytes[argCounter][i] = (sbyte)bytes[i];
}
unsafe
{
fixed (sbyte* junk = &sbytes[0][0])
{
sbyte*[] arrayofptr = new sbyte*[sbytes.Length];
for (int i = 0; i < sbytes.Length; i++)
{
fixed (sbyte* ptr = &sbytes[i][0])
{
arrayofptr[i] = ptr;
}
}
fixed (sbyte** ptrptr = &arrayofptr[0])
{
XFunction(7, ptrptr);
}
}
}

Related

Convert 2D short array to Base64

I have a 2D short array coming from a C++ library. The array contains the pixels of a 16 bit grayscale image. I am trying to convert it to Base64 to display it. My C# code is as follows:
string picture_path = "~/Picture/CT_Axial_Z/CT_Axial-Z_0111.png";
string path = System.Web.Hosting.HostingEnvironment.MapPath(picture_path);
if (File.Exists(path))
{
IntPtr gpget = Open16BitGrayImage(path);
CImage_DLL gget = (CImage_DLL)Marshal.PtrToStructure(gpget, typeof(CImage_DLL));
int short_size = sizeof(short);
int p_s_cursor = 0;
Array pshImageData = Array.CreateInstance(typeof(short), gget.m_nH, gget.m_nW);
for (int i = 0; i < gget.m_nH; i++)
{
for (int j = 0; j < gget.m_nW; j++)
{
short data = (short)Marshal.PtrToStructure(gget.pshImageData + p_s_cursor, typeof(short));
pshImageData.SetValue(data, i, j);
p_s_cursor += short_size;
}
}
}
I need to convert it to Base64 and display it on a canvas. How should I do it?

Memory layout of C# array of struct

In C, if I have the following struct Data:
struct __attribute__((__packed__)) Data
{
double x;
int y;
};
And then create an array named val of this struct:
Data val[3];
All values stored in val (i.e. val[0].x, val[0].y, val[1].x, val[1].y, val[2].x and val[2].y are contiguous in memory.
Now, when having the following struct in C#:
[StructLayout(LayoutKind.Sequential, Pack=0)]
struct Data
{
public double x;
public int y;
}
And then create an array named val of this struct:
Data val[3];
I would expect that all values stored in val are contiguous in memory, which they are not (based on the tests that I have conducted). In details, val[0].x and val[0].y are both contiguous, but they are not contiguous with val[1] (which, in turn, is not contiguous with val[2]).
My question is: in C#, how can I create a variable (that is an array) of a certain struct that all its elements and members are contiguous in memory?
Just to try it, I made a very simple project: using Pack=1 seems to pack perfectly fine to the smallest byte.
Reproducing code (on a console app):
[StructLayout(LayoutKind.Sequential, Pack=1)]
struct Data
{
public double x;
public int y;
}
class Program {
static void Main()
{
Data[] val = new Data[3] {
new Data { x = 0, y = 0 },
new Data { x = 1, y = 1 },
new Data { x = 2, y = 2 },
};
for(var i = 0; i < 3; i++)
{
Console.WriteLine("data[" + i + "].x = " + BitConverter.ToString(BitConverter.GetBytes(val[i].x)));
Console.WriteLine("data[" + i + "].y = " + BitConverter.ToString(BitConverter.GetBytes(val[i].y)));
}
unsafe {
fixed (Data *p = &val[0])
{
byte *c = (byte *)p;
for(var j = 0; j < 3; j++)
{
for(var i = 0; i < Marshal.SizeOf<double>(); i++, c++)
{
if(i!=0) Console.Write("-");
Console.Write("{0:X2}", *c);
}
Console.WriteLine();
for(var i = 0; i < Marshal.SizeOf<int>(); i++, c++)
{
if(i!=0) Console.Write("-");
Console.Write("{0:X2}", *c);
}
Console.WriteLine();
}
}
}
}
}
Output:
data[0].x = 00-00-00-00-00-00-00-00
data[0].y = 00-00-00-00
data[1].x = 00-00-00-00-00-00-F0-3F
data[1].y = 01-00-00-00
data[2].x = 00-00-00-00-00-00-00-40
data[2].y = 02-00-00-00
00-00-00-00-00-00-00-00
00-00-00-00
00-00-00-00-00-00-F0-3F
01-00-00-00
00-00-00-00-00-00-00-40
02-00-00-00
Which looks perfectly continuous to me, unless I'm missing something

How to set all array's elements into one variable in C#

For example i've got one array like
int[] array = {1,0,0,1,0}
and one int variable=0;
I want set all array's elements into variable. How can i do this?
variable=10010
In addition if we think about reverse of this situation? Variable's values set to array?
int something=10000 to int[] something={1,0,0,0,0}
Thanks for your all contribution
//==============go forwards===================
int[] array = { 1, 0, 0, 1, 0 };
int variable = 0;
for (int i = 0; i < array.Length; ++i)
{
//first element
if (i == 0)
variable = array[i];
else
{
variable *= 10;
variable += array[i];
}
}
//print resualts
Console.WriteLine(variable);
//===================go backwards===============
int variable2 = 10010;
//convert it into a char array
string value = variable2+"";
//set the array length based on the size
int[] reverse = new int[value.Length];
//loop
for (int i = 0; i < value.Length; ++i)
{
//grab the number from a char value and push it into the array
reverse[i] = (int)Char.GetNumericValue(value[i]);
}
//print out
for(int i = 0; i <reverse.Length;++i)
{
Console.WriteLine("[" + i + "] = " + reverse[i]);
}
Yet another way to do this, but not as compact as others. This approach demonstrates bit-wise operations to construct an int from the array of 0's and 1's.
class Program
{
// converts array of 0's and 1's to an int, and assumes big endian format.
static int bitArrayToInt(int[] bit_array)
{
int rc = 0;
for (int i = 0; i < bit_array.Length; i++)
{
rc <<= 1; // bit shift left
rc |= bit_array[i]; // set LSB according to arr[i].
}
return rc;
}
static void Main(string[] args)
{
int[] array = { 1, 0, 0, 1, 0 };
int rc = bitArrayToInt(array);
System.Console.WriteLine("{0} = {1} binary",rc, Convert.ToString(rc, 2));
System.Console.ReadLine();
}
}
There's a huge number of choices on how to approach the problem.
Shortest quickest method I could think of.
byte[] array = { 1, 0, 1, 0, 0 };
string temp = "";
int result = 0;
for (int i = 0; i < array.Length; i++)
temp += array[i].ToString();
result = Convert.ToInt32(temp);
I'm on my phone here, so bear with me, but if performance isn't an issue then how about something like:
int.Parse(string.Join(string.Empty, array.Select(d => d.ToString()));
Obviously you'll need some error handling around the parsing for overflows, invalid characters, etc.

Cannot implicitly convert type float to float[]

Getting error Error CS0029 Cannot implicitly convert type 'float' to 'float[]' when trying to compile this code
float[] timeValues;
float time;
while (lineBeingRead != null)
{
valueSplit = lineBeingRead.Split(exerciseDivider);
for (int i = 0; i < valueSplit.Length; i++)
{
if (valueSplit[i].Contains(textToFind))
{
exerciseLine = valueSplit[i];
string[] timeValuesString = exerciseLine.Split(timeDivider);
for (int a = 0; a < timeValuesString.Length; i++)
{
time = float.Parse(timeValuesString[1]);
timeValues = time;
}
}
}
}
Does anyone have any idea what is going on here? I can't figure this out and I couldn't find any answers out there.
You are trying to assign a float number to an array (not adding it as an element of array). So you must first initialize your array with a predefined size: timeValues = new float[neededLength]. But if you don't know the size you need, the List<float> type is better choice as below code:
//float[] timeValues;
List<float> timeValues = new List<float>();
float time;
while (lineBeingRead != null)
{
valueSplit = lineBeingRead.Split(exerciseDivider);
for (int i = 0; i < valueSplit.Length; i++)
{
if (valueSplit[i].Contains(textToFind))
{
exerciseLine = valueSplit[i];
string[] timeValuesString = exerciseLine.Split(timeDivider);
for (int a = 0; a < timeValuesString.Length; i++)
{
time = float.Parse(timeValuesString[1]);
//timeValues = time;
timeValues.add(time);
}
}
}
}
Also you can convert your list to array when needed just by calling it's ToArray method:
var timeArray = timeValues.ToArray();
You need to instantiate your array before using it and you can not assign single flot to whole array. Change following part of your code
string[] timeValuesString = exerciseLine.Split(timeDivider);
timeValues = new float[timeValuesString.Length]; // CHANGE-1
for (int a = 0; a < timeValuesString.Length; i++)
{
time = float.Parse(timeValuesString[1]);
timeValues[a] = time; // CHANGE-2
}

C# Function to translate Binary-Code

Right now I try to write a C# Program to translate 8 Base Binary into Text.
But I guess I am not experienced enough with C# to truly make it Work.
I think the code I come up with, should, from a logical Point-of-View somewhat do what I want, but the Syntax isn't properly doing it, since donĀ“t know it better.
This is what I have so far:
using System;
using System.Linq;
using System.Text;
class binaryTranslate
{
public int convertBin(string CodeInput)
{
int [] code = CodeInput.ToArray();
int CodeCount = code.ToString().Length;
int EightBaseSegAmount = CodeCount / 8;
int ByteCapacity = 8;
StringBuilder translated = new StringBuilder();
for (var i = 1; i < EightBaseSegAmount + 1; i++)
{
StringBuilder Byte = new StringBuilder(ByteCapacity);
int ByteStart = (i * 8) - 8;
int ByteEnd = (i * 8) - 1;
int ByteIncrement = 1;
for (var j = ByteStart ; j < ByteEnd + 1; j++)
{
Byte.Append(code[j]);
}
for (var k = 0; k > 7; k++)
{
int BitValue = 128;
if (Byte[k] == 1)
{
if (k > 0)
{
int Squared = Math.Pow(2, k);
ByteIncrement += BitValue / Squared;
}
else
{
ByteIncrement += BitValue;
}
}
}
char toSymbol = Convert.ToChar(ByteIncrement);
translated.Append(toSymbol);
}
return translated;
}
public static int Main()
{
convertBin("010010000110000101101100011011000110111100100001");
}
}
First of all, your code won't compile. Here are the errors/mistakes.
The first one is, at the first line of your function, you are converting the input string to an array using String.ToArray(), which returns a char[] but your try to assign it to a variable (code) typed int[]. You can solve this by replacing the int[] with either char[] or var.
The second one is, inside the second for loop (k = 0; k > 7), you use Math.Pow() and assign it's return value to an int variable (Squared). But Math.Pow returns double. You can solve this by casting the return value of Math.Pow to int. Like; int Squared = (int)Math.Pow(2, k);
The last thing is not easily solvable like the first two because, your code is not exactly correct. You are trying to return something called translated, which is a variable of type StringBuilder. But your function is defined to return an int.
Now these were compile errors. There are a bunch of logical and decision errors/mistakes. Your algorithm also isn't very correct.
Here is a sample code you can use/examine. I'd like to help you further, why your code was incorrect, what was your design mistakes etc. if you want to.
class binaryTranslate
{
public enum IncompleteSegmentBehavior
{
Skip = 0,
ZerosToStart = 1,
ZerosToEnd = 2
}
private byte ConvertBinstrToByte(string sequence)
{
if (string.IsNullOrEmpty(sequence))
return 0; // Throw?
if (sequence.Length != sizeof(byte) * 8)
return 0; // Throw?
const char zero = '0';
const char one = '1';
byte value = 0;
for (int i = 0; i < sequence.Length; i++)
{
if (sequence[i] != zero && sequence[i] != one)
return 0; // Throw
value |= (byte)((sequence[i] - zero) << (7 - i));
}
return value;
}
private string HandleIncompleteSegment(string segment, int segmentSize, IncompleteSegmentBehavior behavior)
{
string result = null;
var zeroAppender = new StringBuilder();
for (int i = 0; i < segmentSize - segment.Length; i++)
zeroAppender.Append('0');
var zeros = zeroAppender.ToString();
switch (behavior)
{
case IncompleteSegmentBehavior.Skip:
break;
case IncompleteSegmentBehavior.ZerosToStart:
result = zeros + result;
break;
case IncompleteSegmentBehavior.ZerosToEnd:
result = result + zeros;
break;
default:
break;
}
return result;
}
public byte[] ConvertBinstrToBytes(string binarySequence, IncompleteSegmentBehavior behavior = IncompleteSegmentBehavior.Skip)
{
var segmentSize = sizeof(byte) * 8;
var sequenceLength = binarySequence.Length;
var numberOfBytes = (int)Math.Ceiling((double)sequenceLength / segmentSize);
var bytes = new byte[numberOfBytes];
for (int i = 0; i < numberOfBytes; i++)
{
var charactersLeft = sequenceLength - i * segmentSize;
var segmentLength = (charactersLeft < segmentSize ? charactersLeft : segmentSize);
var segment = binarySequence.Substring(i * segmentSize, segmentLength);
if (charactersLeft < segmentSize)
{
segment = HandleIncompleteSegment(segment, segmentSize, behavior);
if (segment == null)
continue;
}
bytes[i] = ConvertBinstrToByte(segment);
}
return bytes;
}
}
This code passes these assertions.
var bytes = new binaryTranslate()
.ConvertBinstrToBytes("00000000");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b00000000);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("10000000");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b10000000);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("11111111");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b11111111);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("00000001");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b00000001);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("1100110000110011");
Assert.Equal(bytes.Length, 2);
Assert.Equal(bytes[0], 0b11001100);
Assert.Equal(bytes[1], 0b00110011);
If you are really converting to a string the code should look like this
namespace binaryTranslate
{
class Program
{
static void Main(string[] args)
{
//convertBin("01001000 01100001 01101100 01101100 01101111 00100001");
string results = BinaryTranslate.convertBin(new byte[] { 0x44, 0x61, 0x6c, 0x6c, 0x6f, 0x21 });
}
}
public class BinaryTranslate
{
public static string convertBin(byte[] CodeInput)
{
return string.Join("", CodeInput.Select(x => x.ToString("X2")));
}
}
}
this should do the trick.
public static string FromBinary(string binary)
{
int WordLength = 8;
binary = binary.Replace(' ', '');
while(binary.Length % WordLength != 0)
binary += "0";
string output = String.Empty;
string word = String.Empty;
int offset = 0;
while(offset < binary.Length)
{
int tmp = 0;
word = binary.Substring(offset, 8);
for(int i=0; i<(WordLength - 1); i++)
if(word[i] == '1')
tmp += (int) Math.Pow(2, i);
output += Convert.ToChar(tmp);
offset += WordLength;
}
return output;
}

Categories

Resources