John
John

Reputation: 475

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

Upvotes: 1

Views: 1972

Answers (2)

PM 2Ring
PM 2Ring

Reputation: 55469

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)

Upvotes: 3

nneonneo
nneonneo

Reputation: 179422

You can simply AND with 0xff to force the result back into the unsigned char range:

return ((~LRC)+1) & 0xff

Upvotes: 2

Related Questions