【问题标题】:Python ctype help: working with C unsigned char pointersPython ctype 帮助:使用 C 无符号字符指针
【发布时间】:2012-03-21 04:50:54
【问题描述】:

我的第一篇文章,所以请放轻松。 :) 我对 Python 也有点陌生,但我喜欢我目前所看到的。我想要做的是访问一个允许我通过 Python 打印到收据打印机的 c 库。我正在使用 ctypes 在 Python 中创建一个包装器,一切都很好,除了两个函数。这是我们的原型:

int C56_api_printer_write(int printer, unsigned char * data, int size, unsigned long timeout_ms);
int C56_api_printer_read(int printer, unsigned char * data, int size, unsigned long timeout_ms);

我的问题是使用 ctypes 写入和读取 unsigned char 指针。我必须在 Python 中读取位图文件并将数组传递给写入函数,或者在读取的情况下,我需要将该指针作为整数数组读取。

在过去的几个小时里,我一直在这个问题上苦苦挣扎,所以我希望专家可以通过发布一个简单的示例来提供帮助,说明如何实现这一点。

谢谢!

【问题讨论】:

    标签: python arrays pointers bitmap ctypes


    【解决方案1】:

    好的,在 Kyss 的帮助下,我得以完成此任务。这是我完成此问题的测试代码和结果:

    我的 test.c 代码:

    #include <stdio.h>
    int test(unsigned char *test, int size){
        int i;
        for(i=0;i<size;i++){
            printf("item %d in test = %d\n",i, test[i]);
        }   
    }
    int testout(unsigned char *test, int *size){
       test[2]=237;
       test[3]=12;
       test[4]=222;
       *size = 5;
    }
    main () {
        test("hello", 5); 
        unsigned char hello[] = "hi";
        int size=0;
        int i;
        testout(hello,&size);
        for(i=0;i<size;i++){
            printf("item %d in hello = %d\n",i, hello[i]);
        }   
    }
    

    我创建了一个 main 来测试我的 c 函数。这是函数测试的输出:

    item 0 in test = 104
    item 1 in test = 101
    item 2 in test = 108
    item 3 in test = 108
    item 4 in test = 111
    item 0 in hello = 104
    item 1 in hello = 105
    item 2 in hello = 237
    item 3 in hello = 12
    item 4 in hello = 222
    

    然后我编译为共享,所以它可以从 python 中使用:

    gcc -shared -o test.so test.c
    

    这是我用于我的 python 代码的内容:

    from ctypes import *
    
    lib = "test.so"
    dll = cdll.LoadLibrary(lib)
    testfunc = dll.test
    print "Testing pointer input"
    size = c_int(5)
    param1 = (c_byte * 5)()
    param1[3] = 235 
    dll.test(param1, size)
    print "Testing pointer output"
    dll.testout.argtypes = [POINTER(c_ubyte), POINTER(c_int)]
    sizeout = c_int(0)
    mem = (c_ubyte * 20)() 
    dll.testout(mem, byref(sizeout))
    print "Sizeout = " + str(sizeout.value)
    for i in range(0,sizeout.value):
        print "Item " + str(i) + " = " + str(mem[i])
    

    还有输出:

    Testing pointer input
    item 0 in test = 0
    item 1 in test = 0
    item 2 in test = 0
    item 3 in test = 235
    item 4 in test = 0
    Testing pointer output
    Sizeout = 5
    Item 0 = 0
    Item 1 = 0
    Item 2 = 237
    Item 3 = 12
    Item 4 = 222
    

    有效!

    我现在唯一的问题在于根据输出大小动态调整 c_ubyte 数组的大小。不过,我已经发布了一个单独的问题。

    感谢您的帮助凯斯!

    【讨论】:

    • *注意:如果我使用 PyPy 运行此代码,它希望我为我的第一个函数声明 argtypes。当我声明它们时,它会出错。所以我不相信我的解决方案是 100% 正确的。
    • 请注意,您的缓冲区 hello 只有三个字符长(包括终止字符串的 null),但 testout 写入 5 个字节。这是一个缓冲区溢出,并破坏了超出内存中“hi\0”字符串位置的内存。
    【解决方案2】:

    以下内容对您有帮助吗?如果它给您带来错误或我误解了您的问题,请告诉我:

    size =
    printer =
    timeout =
    
    data = (ctypes.c_ubyte * size)() # line 5
    
    C56_api_printer_read(printer, data, size, timeout)
    
    # manipulate data eg
    data[3] = 7
    
    C56_api_printer_write(printer, data, size, timeout)
    

    编辑:

    关于第 5 行:另见 http://docs.python.org/library/ctypes.html 第 15.17.1.13 和 15.17.1.20 节。

    (ctypes.c_ubyte * size)
    

    给出了一个构造长度大小的 ctypes 数组的函数。然后在这一行中,我调用不带参数的函数,导致初始化为零。

    【讨论】:

    • Kyss,这很接近。感谢您朝着正确的方向推动。我将在下面发布答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 2023-01-17
    相关资源
    最近更新 更多