如何使用 ctypes 将 byteArray 传递到以 char* 作为参数的 C 函数中?

8 c python ctypes shared-libraries

我在 C 中创建了一个函数,它接受一个 int 大小和一个 char *buffer 作为参数。我想使用 ctypes 从 python 调用这个函数并传入 python byteArray。我知道首先您必须将 C 文件编译成共享库(.so 文件)并使用 ctypes 来调用该函数。这是我到目前为止的代码。

加密.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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是python文件:

import ctypes

encryptPy = ctypes.CDLL('/home/aradhak/Documents/libencrypt.so')
hello = "hello"
byteHello = bytearray(hello)
encryptPy.encrypt(5,byteHello)
encryptPy.decrypt(5,byteHello)
Run Code Online (Sandbox Code Playgroud)

基本上我想从 python 调用 C 方法,通过 python 字节数组,并让它遍历数组并打印每个元素

ori*_*zil 12

Mark 的回答非常有帮助,因为它将字符数组传递给 C 函数,这正是 OP 真正想要的,但是如果有人在这里找到真正想要传递字节数组的方法那么方法似乎是构建一个由字节数组的内存支持的 ctypes.c_char,然后将 .ctypes.c_char 传递给它

我这里的例子忽略了 Mark 推荐的参数声明,这确实是一个好主意。

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
Run Code Online (Sandbox Code Playgroud)

  • TLDR:在 Python 3 中,只需使用“bytes(ba)”(对于不可变缓冲区)或“create_string_buffer(bytes(ba))”(对于可变缓冲区)。 (2认同)

Mar*_*nen 5

您需要的最低要求(Python 2)是:

hello = "hello"
encryptPy.encrypt(5,hello)
encryptPy.decrypt(5,hello)
Run Code Online (Sandbox Code Playgroud)

但是最好声明参数类型和返回值。完整程序:

#!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)
Run Code Online (Sandbox Code Playgroud)

请注意,在传递 python 字节字符串时,请考虑缓冲区不可变。在这种情况下,您只读取缓冲区,但如果您需要允许 C 函数更改字符串,请使用:

hello = ctypes.create_string_buffer('hello',5)
Run Code Online (Sandbox Code Playgroud)

下面也可以工作,但长度为 6。将包括终止空值。

hello = ctypes.create_string_buffer('hello')
Run Code Online (Sandbox Code Playgroud)