This process is made simple with Python’s subprocess module.
Here is the C program I want to call:
#include <stdio.h> void CRC_calcCrc8( unsigned short int *crcReg, unsigned short int poly, unsigned char Data); unsigned short int val=0xFFFF; unsigned short int *reg=&val; unsigned char data_buf[20] = {0}; int main( int argc, char *argv[] ) { char *myString=argv[1]; int myVal; sscanf(myString, "%x", &myVal); int i=0; for(i=1 ; i<argc ; i++) { char *myString=argv[i]; int myVal; sscanf(myString, "%x", &myVal); //printf("The value was read in: it is %0x in hex, or %d in decimal\n", myVal, myVal); data_buf[i-1] = myVal; } for (i=0; i<(argc-1); i++) CRC_calcCrc8(&val,0x1021,data_buf[i]); printf("%d\n",val); return 0; } void CRC_calcCrc8( unsigned short int *crcReg, unsigned short int poly, unsigned char Data) { unsigned short int i; unsigned short int xorFlag; unsigned short int bit; unsigned short int dcdBitMask = 0x80; for(i=0; i<8; i++) { // Get the carry bit. This determines if the polynomial should be // xor'd with the CRC register. xorFlag = *crcReg & 0x8000; // Shift the bits over by one. *crcReg <<= 1; // Shift in the next bit in the data byte bit = ((Data & dcdBitMask) == dcdBitMask); *crcReg |= bit; // XOR the polynomial if(xorFlag) { *crcReg = *crcReg ^ poly; } // Shift over the dcd mask dcdBitMask >>= 1; } //printf("%d\n",*crcReg); }
This CRC calculator function was provided in the datasheet of an RFID reader I am currently using. Instead of trying to replicate this in Python it is easier to just call the C program from Python and get the returned CRC value. The first for loop in the C program contains instructions to convert the arguments passed to the int main function from string to hex values. These hex values are stored in an array and passed to the CRC calculator function one by one.
Here is an example of passing arguments to the above program in the command line:
This python script replicates this using the subprocess module:
import subprocess crc = subprocess.check_output(["./a.out", "5b", "4c", "ff", "09"]) crc= crc.replace("n", "") print 'crc = ' , crc
For fun you could also try the ctypes module. You would import ctypes and reference the .dll or .so file generated by the c compiler.
Then you wouldn’t have to parse the output directly if (say) there was an error caused by one of your arguments.
e.g.
“`
from ctypes import *
# here accessing windows dll msvcrt which uses cdecl compilation style
libc = cdll.msvcrt # could use cdll, windll, oledll to access your dll file depending on how compiled.
print libc.printf
print libc.time(None)
print hex(windll.kernel32.GetModuleHandleA(None))
#
printf = libc.printf
printf(“%d bottles of beern”, 42)
printf(“An int %d, a double %fn”, 1234, c_double(3.14))
printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
printf(“String ‘%s’, Int %d, Double %fn”, “Hi”, 10, 2.2)
“`
more detail here:
– http://python.net/crew/theller/ctypes/tutorial.html
C and C++ hints
– http://stackoverflow.com/questions/7586504/python-accessing-dll-using-ctypes
Cookbook for ctypes
– http://wiki.scipy.org/Cookbook/Ctypes
super useful for more complex C programs that might not have suitable command line interfaces.
I was wondering what the proper way to do it was! Useful info thanks.