2

I just found out about dot42, a C# way to develop native Android Apps.

So my first project way to use some old code for generating CRC8 bytes. I created a new class in the project, copied the code over and tried to use it as normal.

I keep on getting java.lang.VerifyError ??

My class is simple mathematical computation. When I break it out into the main activity as a Public Method it works as expected.

enter image description here

But if I try to use the static class I get that error and I have no idea how to track down what the problem is? I tried adding the various android namespaces, tried making it a normal class to instantiate and even changed it to internal

The method CRC8.Compute("mystring") does not even go into the compute code (if i put a break point there) It just throws and error right there on the method in MainActivity.cs

What do I have to do to use classes like this using dot42? (I looked at various examples on the site and I cannot pin point anything specific that needs to be done)

namespace dot42Application1
{
    public class CRC8
    {
        static byte[] table = new byte[256];
        // x8 + x2 + x + 1 
        const byte poly = 0x07;

        public static string Compute(string ASCI)
        {
            int crcByte = Convert.ToInt16(ComputeChecksum(System.Text.Encoding.ASCII.GetBytes(ASCI)).ToString());
            return crcByte.ToString("000");
        }


        public static byte ComputeChecksum(byte[] bytes)
        {
            byte CRCInitialValue = 0xFF;
            //Final XOR value 0x00;
            //Not revered bytes
            //Not reverse CRC berfore final byte

            if (bytes != null && bytes.Length > 0)
            {
                foreach (byte b in bytes)
                {
                    CRCInitialValue = table[CRCInitialValue ^ b];
                }
            }
            return CRCInitialValue;
        }

        public CRC8()
        {
            for (int i = 0; i < 256; ++i)
            {
                int temp = i;
                for (int j = 0; j < 8; ++j)
                {
                    if ((temp & 0x80) != 0)
                    {
                        temp = (temp << 1) ^ poly;
                    }
                    else
                    {
                        temp <<= 1;
                    }
                }
                table[i] = (byte)temp;
            }
        }




    }
}

Maybe this helps. The stack trace shows...

enter image description here

Piotr Kula
  • 9,597
  • 8
  • 59
  • 85
  • I suspect its a missing decoration as the compiler removes code aggressively to reduce code size... but what should I use?? – Piotr Kula Sep 12 '13 at 16:10

2 Answers2

2

It's indeed a bug in the dot42 compiler, the line:

int crcByte = Convert.ToInt16(...) ends internally as short, which is 16 bit, than the ToString on the int is called, passing the 16 bit value, without upcasting it to 32 bit, resulting in the verify error.

We (the dot42 compiler team) created a case/ticket for this issue.

As workaround, you can change the code into: int crcByte = Convert.ToInt32(...)

Hope this helps.

  • Thanks for coming back about this. I thought it was the way I was declaring the class because I copy and pasted the code. Tommee helped me solve the problem but I am happy that this could help you improve the compile. Keep up the good work! – Piotr Kula Sep 17 '13 at 09:46
  • Another problem I found is that when I return a Byte and inspect the value lets say 205 in Visual Studio but then to a Byte.ToString() I get the value -51. What is happening is the the ToString is converting the unsigned integer to a signed integer and giving me the incorrect integer value. I have to specifically convert the byte to Int16 variable then do a Int16.ToString() to get the desired "205" string. Looks like another bug? Either Visual Studio inspector? Or something in the middle layer implicitly converting it to Int32? Or that is just how Java does it? – Piotr Kula Sep 17 '13 at 21:52
1

Check some possible issues:

  1. A static constructor must be parameterless.
  2. Memeber names can not be the same as their enclosing type.
  3. Properties: best set Android API 8 or higher.
  4. What IDE do you use - maybe here is the problem? (Recommended VS2010)
  5. Do you have the newest dot42 installed, with all the necessary licence and security keys?

I have VS2010 and the newest dot42 plugin installed on Win7 OS, and tried to simulate your class expecting to see the same errors, however everything compiled good. The simulated static class is put in another file, in the same namespace. I call its static methods from another class elsewhere - MainActivity class.

Here is the simulated class:

using System;
using Android.App;
using Android.Os;
using Android.Widget;
using Dot42;
//using Dot42.Manifest;

namespace MyNamespace
{
    public  class CRC8
    {
        static byte[] table = new byte[256];
        //x8 + x2 + x + 1
        const byte poly = 0x07;

        public static byte getCRC(byte[] _bytes)
        {      return _bytes[0];
        }

        public static byte getCRC(String str_bytes)
        {      return (byte) str_bytes.CharAt(0); 
        }
         static  CRC8()
        {
            //nothing happens so far
        }
    }
}

Here is the call within MainActivity class:

protected override void OnCreate(Bundle savedInstance)
        {
            base.OnCreate(savedInstance);
            SetContentView(R.Layouts.MainLayout);

            TextView text_view = (TextView)FindViewById(R.Ids.textView1);

            byte[] aa = { 125, 54, 67, 78, 89 };
            byte b_ret = 0;

            b_ret = CRC8.getCRC("Ala ma kota");
            text_view.Text += "CRC8.getCRC(String): " + b_ret.ToString() + "\n";

            b_ret = CRC8.getCRC(aa);
            text_view.Text += "CRC8.getCRC(byte[]): " + b_ret.ToString() + "\n";

            text_view.Text += "CRC8.getCRC(ASCII.GetBytes): ";
            text_view.Text += CRC8.getCRC(System.Text.Encoding.ASCII.GetBytes("ABC123XYZ")).ToString() + "\n";
        }

Here is the output (API 18 i.e. Android 4.3):

  • CRC8.getCRC(String): 65
  • CRC8.getCRC(byte[]): 125
  • CRC8.getCRC(ASCII.GetBytes): 65

Can you find any difference between our codes and so on? I hope this helps.

TomeeNS
  • 455
  • 4
  • 10
  • Thank you. I did declare the outer class `internal static class CRC8` but it seems like you declared it `public class CRC8` - Possibly the class must not be static? I tried your example with my code but it does not work still. Please check my question I put the whole CRC8 Class in there. My android version is 10 and my target SDK is 16 – Piotr Kula Sep 15 '13 at 11:19
  • It is weird. I copied your code and yet it does work!? The only difference is that my constructor generates a bytes table and your constructor is empty? – Piotr Kula Sep 15 '13 at 11:30
  • I think somethign is wrong with the Compute method. I copied all the code to your example and it worked, until I copied Compute()... I think it does not like the ToString masking or the Int16 conversion. But debugger does not even go in there. Thanks for your help! – Piotr Kula Sep 15 '13 at 11:36
  • 1
    I got the same error when I used your Compute(String ASCI) method. But after splitting the code into several lines be problem dissapears. It must probably be some Java/Android limitation regarding maybe the stack usage or dot42's compiler/linker is faulty. Your code in Compute after splitting seems fine, but I got to compressing it to only one line, and working, here: public static String Compute(String ASCI) { return ComputeChecksum(System.Text.Encoding.ASCII.GetBytes(ASCI)).ToString("000"). Best Regards! – TomeeNS Sep 15 '13 at 21:38
  • Many thanks! I think its dot42 linker. They still trying very hard to get allot of things working. But - It is pretty awesome any way. Pozdrawiam! – Piotr Kula Sep 15 '13 at 22:21