问题
I have created a function in C which takes an int size and a char *buffer as arguments. I would like to use ctypes to call this function from python and pass in a python byteArray. I know that first you must compile the C file into a shared library (.so file) and use ctypes to call that function. Here's the code I have so far.
encrypt.c:
#include <stdio.h>
void encrypt(int size, unsigned char *buffer);
void decrypt(int size, unsigned char *buffer);
void encrypt(int size, unsigned char *buffer){
for(int i=0; i<size; i++){
unsigned char c = buffer[i];
printf("%c",c);
}
}
void decrypt(int size, unsigned char *buffer){
for(int i=0; i<size; i++){
unsigned char c = buffer[i];
printf("%c",c);
}
}
And here's the python file:
import ctypes
encryptPy = ctypes.CDLL('/home/aradhak/Documents/libencrypt.so')
hello = "hello"
byteHello = bytearray(hello)
encryptPy.encrypt(5,byteHello)
encryptPy.decrypt(5,byteHello)
Basically I want to call the C method from python, pass through a python byte array, and have it iterate through the array and print each element
回答1:
Mark's answer is quite helpful in that it passes a character array to C, which is what the OP really wanted, but in case there's folks finding their way here who really want to pass a byte-array, an approach seems to be to build a ctypes.c_char backed by the memory of your byte-array, and pass that.
note my example here disregards the argument declaration recommend by Mark, which indeed seems like a good idea.
import ctypes
# libFoo.c:
# (don't forget to use extern "C" if this is a .cpp file)
#
# void foo(unsigned char* buf, size_t bufSize) {
# for (size_t n = 0; n < bufSize; ++n) {
# buf[n] = n;
# }
# }
fooLib = ctypes.cdll.LoadLibrary('./lib/libFoo.dylib')
ba = bytearray(10)
char_array = ctypes.c_char * len(ba)
fooLib.foo(char_array.from_buffer(ba), len(ba))
for b in ba:
print b
# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
回答2:
The minimum you need (Python 2) is:
hello = "hello"
encryptPy.encrypt(5,hello)
encryptPy.decrypt(5,hello)
But it is good to declare the argument types and return values as well. Full program:
#!python2
import ctypes
encryptPy = ctypes.CDLL('/home/aradhak/Documents/libencrypt.so')
encryptPy.encrypt.argtypes = (ctypes.c_int,ctypes.c_char_p)
encryptPy.encrypt.restype = None
encryptPy.decrypt.argtypes = (ctypes.c_int,ctypes.c_char_p)
encryptPy.decrypt.restype = None
hello = "hello"
encryptPy.encrypt(len(hello),hello)
encryptPy.decrypt(len(hello),hello)
Note that when passing a python byte string, consider the buffer immutable. In this case you only are reading the buffer, but if you need to allow the C function to mutate the string use:
hello = ctypes.create_string_buffer(5,'hello')
This works as well, but will be length 6. A terminating null will be included.
hello = ctypes.create_string_buffer('hello')
来源:https://stackoverflow.com/questions/37422662/how-can-i-use-ctypes-to-pass-a-bytearray-into-a-c-function-that-takes-a-char-as