Search code examples
pythonc++unsigned-char

Inverse unsigned char in Python


I have the code in C++:

unsigned char LRC_form(char* cadr)
{
  unsigned char LRC=0;
  unsigned int t=0;
  LRC=0;
  for (t=1;t<0x0D;t=t+2)
  {
    LRC=LRC+ASCII2hex(cadr[t])*16+ASCII2hex(cadr[t+1]);
  }
  return ((~(LRC))+1);
}
int main(int argc, char *argv[])
{
    char *p={":010600000045"};
    cout<<LRC_form(p);
}

where ASCII2Hex is a function which translate ASCII code of a char to HEX. I must write the same in Python so I do this:

def LRC_FORM():
    LRC=0
    string_to_send = "010600000045"
    Arr = list(string_to_send)
    #LRC = int(Arr[1])+2
    #print(LRC)
    counter=0
    for i in string_to_send:
        numb = int(i, 16)
        if counter%2 == 0:
            LRC = LRC + numb * 16
        else:
            LRC = LRC + numb
        counter = counter + 1

But how should I implement (~LRC) + 1 since LRC is a unsigned char, in my case it is int, I can use some module like ctypes or struct, but when I do it like this:

import ctypes
import struct
cchar1=(struct.pack('1B',LRC)) 
cchar2= ctypes.c_char(LRC) 

it does not give me result I am expecting. LRC = 77, and I though I should get LRC = '77', but I am getting b'L' so it does not give the same result like code in C++. How can I convert it the correct way?

Thank you in advance!

P.S. output of C++ program

char *p={":010600000045"};
cout<<LRC_form(p);

is giving 76 I am trying to get the same with Python 3

EDIT 1

return LRC; 

in C program gives 76. and it is the same I can get in my Python code. but

return ((~(LRC))+1);

gives 180 and I do not know what should I do to get the same in Python..

EDIT 2

ASCII2Hex function:

unsigned char ASCII2hex (char ASCII)
{
  if (ASCII<0x40)
    return (ASCII-0x30);
  else
    return (ASCII-0x37);
}
    enter code here

Solution

  • The easy way to do this is to let binascii.unhexlify do most of the work. We just have to send it a bytes string, not a text string.

    import binascii
    
    def lrc(s):
        # Convert string s to bytes
        b = s.encode('ascii')
    
        # Interpret hex data in b
        h = binascii.unhexlify(b)
    
        # Add the byte values
        return sum(h)
    
    # test
    
    s = "010600000045"
    print(lrc(s))
    

    output

    76
    

    We can make that function much more compact, although the result is less readable:

    def lrc(s):
        return sum(binascii.unhexlify(s.encode('ascii')))
    

    We can easily do ((~(LRC))+1) in Python, but we have to be careful, for two reasons. Firstly, Python doesn't have unsigned integers, secondly, Python's integers are of unlimited precision. But we can deal with both of those things by supplying a suitable mask. If we want to restrict the result to 8 bits we can use a mask of 0xff == 255:

    l = 76
    print(l, (0xff & ~l) + 1)
    

    output

    76 180
    

    Or we can do the addition after inverting the bits but before we do the masking:

    0xff & (~l + 1)