I have the following two functions in a VB.Net DLL. They emulate the CVL$ and MKL$ functions of old BASIC.
The function CVL takes a 4 byte string and converts it to an Int32 Integer. The MKL function does the opposite.
The functions are used internally in the DLL. When the DLL is called from a VB.NET project all works fine. When the DLL is called from C# the values are totally incorrect. Obviously the problem is with the encoding, but I've tried all of the options available (ASCII, UTF7, UTF8) but none work. Any ideas?
Function CVL(ByVal Value As String) As Integer
Dim Encoding As System.Text.Encoding = System.Text.Encoding.Default
Dim Bytes() As Byte = Encoding.GetBytes(Value)
Return BitConverter.ToInt32(Bytes, 0)
End Function
Function MKL(ByVal Value As Integer) As String
Dim Encoding As System.Text.Encoding = System.Text.Encoding.Default
Dim Bytes() As Byte = BitConverter.GetBytes(Value)
Return Encoding.GetString(Bytes)
End Function
CodePudding user response:
string
isn't a byte buffer, it has very hard rules for encoding. I can easily see how the normal encoding rules will lengthen or shorten the resulting bytes that you're then using to convert to an integer. In fact, even if everything works perfectly, your string has twice as many bytes as the resulting integer. Have you given half a thought about what happens to the other 4 bytes you're silently dropping?
Either do the right thing and use byte buffers (or even better spans), or do your own manual decoding from strings to integers and the other way around. Writing something equally broken, but at least well defined, is pretty trivial:
static int CVL(string s) =>
s[3] << 24 | s[2] << 16 | s[1] << 8 | s[0];
CodePudding user response:
Solution to problem.
- Upgrade project to .NET 6 (https://dotnet.microsoft.com/en-us/platform/upgrade-assistant/tutorial/install-upgrade-assistant)
- Add System.Text.Encoding.CodePages NuGet package to solution
- Register encoding in startup.
- Create a global variable (Encod in the sample) and assign to encoding in startup
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)
Encod = Encoding.GetEncoding(1252)
- Modify the functions to use encoding.
Function CVL(ByVal Value As String) As Integer
Dim Encoding As System.Text.Encoding = Encod
Dim Bytes() As Byte = Encoding.GetBytes(Value)
Return BitConverter.ToInt32(Bytes, 0)
End Function
Function MKL(ByVal Value As Integer) As String
Dim Encoding As System.Text.Encoding = Encod
Dim Bytes() As Byte = BitConverter.GetBytes(Value)
Return Encoding.GetString(Bytes)
End Function
I still don't understand why the C# program would affect the VB.Net program internally but this code solves the problem.
Thanks to those who gave me a couple of good ideas.