i need to migrate some delphi code to c# (.net) for my mv4 apliccation. which will replace some functionalities of the existing delphi aplication, but i need to use some specific function.
the main problem is when i try to get a char from a string like:
FText = "123456";
i = 1;
delphi:
a := Integer(FText[i]);
c#:
a = (int)FText[i];
but c# returns 50 and delphi 49
Delphi has historically used "Length-prefixed" strings where the length indicator was a string[0]. Placing the first character of the string at index 1. Since the introduction of "long strings" in Delphi, the byte count is no longer at index 0, but the strings continue to use 1-based indexing.
C# uses zero-based indexing for strings. When you convert any string code from Delphi to C#, you will need to deal with the different indexing scheme.
C# code works OK. FText[1] == '2' so it's 50 in ASCII.
Don't know lot about Delphi but maybe tables there are not 0-indexed so FText[1] == '1' so its 49 ?
Related
I am translating a python communication library into C#, and am having trouble interpreting how the string gets formatted before being sent over tcp.
The relevant portion of the code is as follows:
struct.pack(
'!HHBH'+str(var_name_len)+'s',
self.msg_id,
req_len,
flag,
var_name_len,
self.varname
)
Then it gets sent with: sendall()
I have looked at the Python documentation (https://docs.python.org/2/library/struct.html) but am still drawing a blank regarding the first line: '!HHBH'+str(var_name_len)+'s', I understand this is where the formatting is set, but what it is being formatted to is beyond me.
The python code that I am translating can be found at the following link:
https://github.com/linuxsand/py_openshowvar/blob/master/py_openshowvar.py
Any python and C# vigilantes out there that can help me build this bridge?
Edit: Based on jas' answer, I have written the following c# struct:
public struct messageFormat
{
ushort messageId;
ushort reqLength;
char functionType;
ushort varLengthHex;
string varname;
...
Once I populate it, I will need to send it over TCP. I have an open socket, but need to convert to to a byte[] I assume so I can use socket.send(byte[])?
Thanks
What's being formatted are the five arguments following the format string. Each argument has a corresponding element in the format string.
For the sake of the explanation, let's assume that var_name_len has the value 12 (presumably because var_name is a string of length 12 in this hypothetical case).
So the format string will be
!HHBH12s
Breaking that down according to the docs:
! Big-ending byte ordering will be used
H self.msg_id will be packed as a two-byte unsigned short
H req_len will be packed as above
B flag will be packed as a one-byte unsigned char
H var_name_len will be packed as a two-byte unsigned short
12s self.varname will be packed as a 12-byte string
I am trying to rewrite old code written in C++ to C# - code does binary manipulation with chars, but I recieve different results (probably I do some bad manipulation because of Unicode in C#).
I need to rewrite this C++ code to C#:
myChar = 'K' ^ 128;
Result of this code in C++ is -53 ('Ë') in C++'s data type char.
Same operation in C# results in 203 (again 'Ë') in C#'s data type char.
So char is ok, but I need same byte value as in C++ (because I do math operation with that). Can you recommend way, how to safe convert C# char to equivalent C++ byte values?
Thanks
In a single byte two's complement representation 203 is an unsigned interpretation of of -53.
If you would like to use an equivalent representation of C++ signed char, the type should be sbyte:
sbyte myChar = (sbyte)('K' ^ 128);
Note that C++ standard leaves it up to the implementation to decide whether a char is signed or unsigned, which means that some standard-compliant C++ will print 203 for myChar, not -58, without any change to your code.
I am developing a wrapper library that allow my project using a x86 C++ dll library in any CPU environment, I have no control about the dll thus I am using DllImport in C#.
There is a provided function which declared in C++: int __stdcall Func(int V, unsigned char *A)
and provided a sample declaration in VB: Private Declare Function Func Lib "lib.dll" Alias "_Func#8" (ByVal V As Long, A As Any) As Long
This function will request a device to Add/Deduct a value to/from a card by passing Convert.ToInt64(decimalValue) as V, and some customize information in A.
Here is the description of A:
It is a byte pointer containing 7 bytes.
The first 5 bytes are used to stores info that will be passed to the card log (The last 4 digits of the receipt number should be included in the first 2 bytes, the other 3 could be A3A4A5)
The last 2 bytes are used to stores info that will be passed to the device (The last 4 digits of the receipt number)
On return, the A contains a 32 bytes data.
After hours and hours of researches and tries, I cannot make result other than 'Access Violation Exception'. Please see the following draft code:
[DllImport("lib.dll", EntryPoint="_Func#8")]
public static external Int64 Func(Int64 V, StringBuilder sb);
string ReceiptNum = "ABC1234";
decimal Amount = 10m;
byte[] A = new byte[32];
A[0] = Convert.ToByte(ReceiptNum.Substring(3, 2));
A[1] = Convert.ToByte(ReceiptNum.Substring(5));
A[2] = Convert.ToByte("A3");
A[3] = Convert.ToByte("A4");
A[4] = Convert.ToByte("A5");
A[5] = Convert.ToByte(ReceiptNum.Substring(3, 2));
A[6] = Convert.ToByte(ReceiptNum.Substring(5));
StringBuilder sb = new StringBuilder(
new ASCIIEncoding().GetString(A), A.Length
);
Int64 Result = Func(Convert.ToInt64(Amount), sb);
And at this point it throws the exception. I have tried passing IntPtr, byte*, byte (by A[0]), byval, byref and none of them works. (Tried to deploy as x86 CPU as well)
Would appreciate any help! Thanks for your time!
PS - The reason of using StringBuilder is the library contains a function that accept a "char *Data" parameter that causes the same exception, and the solution is using StringBuilder to pass as a pointer, this function's VB Declaration is: Private Declare Function Func1 Lib "lib.dll" Alias "_Func1#12(ByVal c As Byte, ByVal o As Byte, ByVal Data As String) As Long
Your external definition is wrong.
StringBuilder is a complex structure containing an array of c# char.
c# chars are utf-16 (double bytes with complex rules for decoding unicode multichar caracters). Probably not what your are seeking.
If your data is a raw byte bufer you should go for byte[]
Int64 is also c# long.
Well, your native method signature takes int, and you're trying to pass a long long. That's not going to work, rather obviously. The same is true with the return value. Don't assume that VB maps clearly to VB.NET, much less C# - Long means a 32-bit integer in VB, but not in .NET. Native code is a very complex environment, and you better know what you're doing when trying to interface with native.
StringBuilder should only be used for character data. That's not your case, and you should use byte[] instead. No matter the fun things you're doing, you're trying to pass invalid unicode data instead of raw bytes. The confusion is probably from the fact that C doesn't distinguish between byte[] and string - both are usually represented as char*.
Additionally, I don't see how you'd expect this wrapper to work in an AnyCPU environment. If the native DLL is 32-bit, you can only use it from a 32-bit process. AnyCPU isn't magic, it just defers the decision of bit-ness to runtime, rather than compile-time.
We've to implement an encryption for an external interface. The owner of the interface has given documentation of how to preform the same encryption on our side. However, this documentation is in C# and we work in PHP.
Most of the parts we understand except for where they seem to typecast a hash to an int. Their code reads:
// hashString exists and is a md5 a like string
int[] keyBuffer = new int[hashString.length];
for (int i=0; i<hashString.length; i++) {
keyBuffer[i] = (int)hashString[i];
}
In PHP, when casting a letter as int, you get 0 (int). As we can't imagine this is what the third party means, we believe C# does something else.
Does C# also cast to int 0, or possibly to a char?
Second, the original hashString is 320 long. This means the code will be creating an int which is 320 long?? In PHP you don't have this idea of reserving memory as C# does here. But when we try to typecast a 320 long string to an int we get an int which is 19 'chars' long.
Does C# also create a shorter int when typecasting a really long 'number' in a string?
You're converting a char to int. A char is a UTF-16 code unit - an unsigned 16-bit integer (the range is [0, 65535]). You get that value, basically, widened to a 32-bit signed integer. So 'A' ends up as 65, for example, and the Euro symbol (U+20AC) ends up as 8364 (0x20ac).
As for your second part - you're creating an int, you're creating an int array. An yes, you'll be creating an array with 320 elements.
C# strings are UTF16. When you cast a UTF16 character to an int, it merely copies the 16-bit UTF16 character value into the 32-bit int.
C# can cast a character to an int and will give you the character code.The code above is taking a string, hashString, and turning it into an array of integers, keybuffer. C# is capable of treating a string like an array of chars using the indexer [] syntax. The code above will produce an array of ints, one per character in the hash string, and each int will be the character code of the corresponding character.
To expand on Jon Skeet's post, your "decimal" integer values will map to the corresponding char values like in the chart below (which I have had on my development PCs for years).
So, casting the integer value 0 to a char will return a NULL.
EDIT: Looking at your original question, it is possible you would be better served looking at an MD5 Example instead of casting the string to an array of integers.
The code actually cast the char (normally ASCII) into an int, not '0' to 0. So if the original string is "d131dd02c5e6eec4", the resulting array will be int[]{100, 49, 51, 49, 100, 100, 48, 50, 99, 53, 101, 54, 101, 101, 99, 52}.
So I imagine you need the function ord in your PHP script.
EDIT:
A bit remarks, casting a string to int in PHP may actually phrase it into int, and the largest int PHP handles is either 32-bit or 64-bit depending on the OS, that's why you get a 19-char long int, which is the maximum of 64-bit int.
In C#, there is another variable type called char, which represents one unicode character, and can cast directly into integer. You cannot cast a string in C# into an int directly in C#.
EDIT2:
I imagine your PHP script to look like this:
<?php
$keyBuffer = new array();
for ($i=0; $i<strlen($hashString); $i++) {
$keyBuffer[$i] = ord($hashString[i]);
}
?>
I need to create a structure or series of strings that are fixed lenght for a project I am working on. Currently it is written in COBOL and is a communication application. It sends a fixed length record via the web and recieves a fixed length record back. I would like to write it as a structure for simplicity, but so far the best thing I have found is a method that uses string.padright to put the string terminator in the correct place.
I could write a class that encapsulates this and returns a fixed length string, but I'm hoping to find a simple way to fill a structure and use it as a fixed length record.
edit--
The fixed length record is used as a parameter in a URL, so its http:\somewebsite.com\parseme?record="firstname lastname address city state zip". I'm pretty sure I won't have to worry about ascii to unicode conversions since it's in a url. It's a little larger than that and more information is passed than address, about 30 or 35 fields.
Add the MarshalAs tag to your structure. Here is an example:
<StructLayout (LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure OSVERSIONINFO
Public dwOSVersionInfoSize As Integer
Public dwMajorVersion As Integer
Public dwMinorVersion As Integer
Public dwBuildNumber As Integer
Public dwPlatformId As Integer
<MarshalAs (UnmanagedType.ByValTStr, SizeConst:=128)> _
Public szCSDVersion As String
End Structure
http://bytes.com/groups/net-vb/369711-defined-fixed-length-string-structure
You could use the VB6 compat FixedLengthString class, but it's pretty trivial to write your own.
If you need parsing and validation and all that fun stuff, you may want to take a look at FileHelpers which uses attributes to annotate and parse fixed length records.
FWIW, on anything relatively trivial (data processing, for instance) I'd probably just use a ToFixedLength() extension method that took care of padding or truncating as needed when writing out the records. For anything more complicated (like validation or parsing), I'd turn to FileHelpers.
byte[] arrayByte = new byte[35];
// Fill arrayByte with the other function
//Convert array of byte to string chain
string arrayStringConverr = Encoding.ASCII.GetString(arrayByte, 0, arrayByte.Length);
As an answer, you should be able to use char arrays of the correct size, without having to marshal.
Also, the difference between a class and a struct in .net is minimal. A struct cannot be null while a class can. Otherwise their use and capabilities are pretty much identical.
Finally, it sounds like you should be mindful of the size of the characters that are being sent. I'm assuming (I know, I know) that COBOL uses 8bit ASCII characters, while .net strings are going to use a UTF-16 encoded character set. This means that a 10 character string in COBOL is 10 bytes, but in .net, the same string is 20 bytes.