Monotouch how to retrieve objectAtIndex from NSArray in C# - c#

In objectiveC given an NSArray fred containing strings I can say:
NSString *s = [fred ObjectAtIndex:5];
What is the c# equivalent? Rosetta stone says to use the method ValueAt but that returns an IntPtr.
var i = fred.ValueAt(5);
But then you are left with how to convert an IntPtr to NSString pointer.

Going via IntPtr feels like a bad idea. Instead, as long as you know the type of the item you want to get, you can just use the following:
int index = 0;
NSString str = myNsArr.GetItem<NSString>(index);

I've came to the same situation.
You can convert that IntPtr to an NSString with new NSString(), like:
string strValue = new NSString(nsArr.ValueAt(1));
It's probably too late for you, but maybe it will help other people.

string strValue = NSString.FromHandle(nsArr.ValueAt(1));

Related

Compare method for type int

I want to do the following but the only issue is that my input query is int not string and also I am searching from my RoomID which is also an integer and not a string. Let me simplify it, instead of _context.Customers.Name, I am comparing from _context.Room.Id which is an int type. This is an obligation and I have to do this. Guys ignore the .Select(Mapper.Map<>) Method, the primary focus is the int problem. I'd appreciate some help.
One way to solve it is to convert the integers to string and do a contain.
Ex.
var needle = 234;
var haystack = 79234826;
var contains = haystack.ToString().Contains(needle.ToString());
If you want to search as if both ints are strings, just let them be strings:
int source = 79234826;
int toFind = 234;
bool found = source.ToString().Contains(toFind.ToString());

Convert single byte character string (half width) to double byte (full width)

Recently I came across this code in a C# application.
cDataString = Strings.StrConv(cDataString, VbStrConv.Wide);
I understand that the StrConv is a string function of VB. You can call it by including 'using Microsoft.VisualBasic;'.
It is supposed to covert half width japanese characters into full width ones.
My question is:
Is there a way to achieve the same WITHOUT using the VB functions and WITHOUT including the VB headers, using only the standard c# functions? I know there are many c# string conversion functions and some of them can convert from unicode to ansi and vice versa and so on. But I am not sure if any of those will directly get the exact same result as the above VB one. So, can this be done in c#?
Thank you for your time and efforts.
Update:
I came across this question that was asked 5 years ago. The answers and discussions do show some ways in which it could be done. What I would specifically like to know is that, after 5 years and new versions and what nots, is there a simpler and better way to do this in .NET without depending on VB functions or VB libraries?
There is no equivalent function in C#.
If you follow the source code for Microsoft.VisualBasic.dll's StrConv, you'll see it actually p/invokes LCMapString internally similar to the answer you linked.
If you don't want to reference Microsoft.VisualBasic.dll, you could wrap the p/invoke into a helper class or service written in C#, something like this...
// NOTE: CODE NOT TESTED
// Code from John Estropia's StackOverflow answer
// https://stackoverflow.com/questions/6434377/converting-zenkaku-characters-to-hankaku-and-vice-versa-in-c-sharp
public static class StringWidthHelper
{
private const uint LOCALE_SYSTEM_DEFAULT = 0x0800;
private const uint LCMAP_HALFWIDTH = 0x00400000;
private const uint LCMAP_FULLWIDTH = 0x00800000;
public static string ToHalfWidth(string fullWidth)
{
StringBuilder sb = new StringBuilder(256);
LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_HALFWIDTH, fullWidth, -1, sb, sb.Capacity);
return sb.ToString();
}
public static string ToFullWidth(string halfWidth)
{
StringBuilder sb = new StringBuilder(256);
LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_FULLWIDTH, halfWidth, -1, sb, sb.Capacity);
return sb.ToString();
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern int LCMapString(uint Locale, uint dwMapFlags, string lpSrcStr, int cchSrc, StringBuilder lpDestStr, int cchDest);
}
Otherwise, you could build a Dictionary to act as a look-up table.
Not a generic solution, but in my particular case (Half-width Japanese katakana ラーメン to Full-width katakana ラーメン), String#Normalize with NFKC option did the job.
Note that this method is not entirely compatible with VB one (e.g. it converts full-width numbers 42 to half-width numbers 42), so you need to select characters to replace like:
// Half-width katakana to Full-width katakana
Regex halfKatakana = new Regex(#"[\uFF61-\uFF9F]+");
cDataString = halfKatakana.Replace(cDataString, (m) => m.Value.Normalize(NormalizationForm.FormKC));

PInvoke char* in C DLL handled as String in C#. Issue with null characters

The function in C DLL looks like this:
int my_Funct(char* input, char* output);
I must call this from C# app. I do this in the following way:
...DllImport stuff...
public static extern int my_Funct(string input, string output);
The input string is perfectly transmitted to the DLL (I have visible proof of that). The output that the function fills out although is wrong. I have hexa data in it, like:
3F-D9-00-01
But unfortunately everything that is after the two zeros is cut, and only the first two bytes come to my C# app. It happens, because (I guess) it treats as null character and takes it as the end of the string.
Any idea how could I get rid of it? I tried to specifiy it as out IntPtr instead of a string, but I don't know what to do with it afterwards.
I tried to do after:
byte[] b1 = new byte[2];
Marshal.Copy(output,b1,0,2);
2 should be normally the length of the byte array. But I get all kind of errors: like "Requested range extends past the end of the array." or "Attempted to read or write protected memory..."
I appreciate any help.
Your marshalling of the output string is incorrect. Using string in the p/invoke declaration is appropriate when passing data from managed to native. But you cannot use that when the data flows in the other direction. Instead you need to use StringBuilder. Like this:
[DllImport(...)]
public static extern int my_Funct(string input, StringBuilder output);
Then allocate the memory for output:
StringBuilder output = new StringBuilder(256);
//256 is the capacity in characters - only you know how large a buffer is needed
And then you can call the function.
int retval = my_Funct(inputStr, output);
string outputStr = output.ToString();
On the other hand, if these parameters have null characters in them then you cannot marshal as string. That's because the marshaller won't marshal anything past the null. Instead you need to marshal it as a byte array.
public static extern int my_Funct(
[In] byte[] input,
[Out] byte[] output
);
That matches your C declaration.
Then assuming the ANSI encoding you convert the input string to a byte array like this:
byte[] input = Encoding.Default.GetBytes(inputString);
If you want to use a different encoding, it's obvious how to do so.
And for the output you do need to allocate the array. Assuming it's the same length as the input you would do this:
byte[] output = new byte[input.Length];
And somehow your C function has got to know the length of the arrays. I'll leave that bit to you!
Then you can call the function
int retval = my_Funct(input, output);
And then to convert the output array back to a C# string you use the Encoding class again.
string outputString = Encoding.Default.GetString(output);

List of Tuple trouble

edit: solved, sorry about this, was due to a typo.
This code.
List<Tuple<Int16, Int16>> a = new List<Tuple<Int16, Int16>>();
Tuple<UInt16, UInt16> b = Tuple.Create<UInt16, UInt16>(4, 2);
a.Add(b);
Produces the following error for a.Add(b)
The best overloaded method match for
'System.Collections.Generic.List<System.Tuple<short,short>>
.Add(System.Tuple<short,short>)'
has some invalid arguments.
In short
List<Tuple<short,short>>.Add(Tuple<short,short>)
has invalid arguments
I can't see how this is.
Tuple<Int16, Int16> and Tuple<UInt16, UInt16> are two different type of tuple.
You are trying to add an UInt16 pair to a list of Int16 pairs. That doesn't work.
You can add an Int16 pair to a list of Int16 pairs:
List<Tuple<Int16, Int16>> a = new List<Tuple<Int16, Int16>>();
Tuple<Int16, Int16> b = Tuple.Create<Int16, Int16>(4, 2);
a.Add(b);
UInt is not an Int
Reference: http://msdn.microsoft.com/en-us/library/yht2cx7b.aspx
It's telling you exactly the problem and the solution. Try the short instead of unsigned short

Migrate function C++ with pointers to C#

I have a function in C++ that returns pointer values​​:
fPosFirst( int &aId, char *aNname, char *aDirectory );
My syntax in c# is:
fPosFirst(ref int aId, String aNname, String aDirectory);
the function returns the id but not the string parameters that anyone knows?
If you want the parameters to be used for returning values then mark them as ref or out.
E.g.
fPosFirst(ref int aId, out string aNname, out string aDirectory);
Assuming that the native function does not "return pointers" but writes characters to the memory locations specified by aNname and aDirectory, you should be able to pass a StringBuilder with a proper capacity to the native function:
void fPosFirst(ref int aId, StringBuilder aNname, StringBuilder aDirectory);
Usage:
var aId = 0;
var aNname = new StringBuilder(260);
var aDirectory = new StringBuilder(260);
fPosFirst(ref aId, aNname, aDirectory);
You need to make the string parameters ref or out if you want to assign to them within the method and have those values available outside the method.
You need to use out keyword before parameters names (example). But actually this is not good practice in C#

Categories