在Python中实现char const * const names []的最佳方法是什么

时间:2018-08-21 19:23:51

标签: python ctypes

我需要将“ char const * const names [] ”参数传递给C API。如何在python ctypes中获得指向常量char的常量指针?

我尝试使用 string1 =“ Hello First” 名称= ctypes.c_wchar_p(string1)

来自C的Api调用为: char const * const names [] = {“ AVeryLongName”,“ Name”};

2 个答案:

答案 0 :(得分:0)

您应该先查看[Python 3]: ctypes - A foreign function library for Python。几个想法:

  • 您不能通过 ctypes 指定 const ness(或者至少我不知道如何)。关于 Win 的一个小例子:

    >>> from ctypes import wintypes
    >>> wintypes.LPCSTR == wintypes.LPSTR
    True
    

    因此,数组的 ctypes 包装器与char *names[] = ....

  • 的包装器相同
  • Python 3 开始,( 8 位)char序列(ctypes.c_char_p不再是str对象,而是[Python 3]: Bytes。它具有大多数常规字符串功能,但是在声明文字时,必须在其前面加上b

    >>> s = "Some string"
    >>> type(s)
    <class 'str'>
    >>> b = b"Some string"
    >>> type(b)
    <class 'bytes'>
    

    注意:要将常规字符串转换为 bytes ,请使用[Python 3]: str.encode(encoding="utf-8", errors="strict")"Dummy string".encode()

  • 无法通过 Python 完成大小不一的(char*)数组;有两种解决方法:

    1. 声明一个大小合适的数组
    2. 声明一个指针(类型:ctypes.POINTER(ctypes.c_char_p)


    我们来看一个 #1的简短示例。

    >>> ARRAY_DIM = 2
    >>> CharPArr = ctypes.c_char_p * ARRAY_DIM
    >>> CharPArr
    <class '__main__.c_char_p_Array_2'>
    >>> names = CharPArr(b"AVeryLongName", "Name".encode())
    >>> names, names[0], names[1]
    (<__main__.c_char_p_Array_2 object at 0x000002E6DC22A3C8>, b'AVeryLongName', b'Name')
    

    names对象(上方)可以传递给接受char const *const names[]的函数,尽管我不确定该函数将如何确定数组的长度(除非另有参数)保持其长度)。

    Python 2 相同:

    >>> ARRAY_DIM = 2
    >>> CharPArr = ctypes.c_char_p * ARRAY_DIM
    >>> CharPArr
    <class '__main__.c_char_p_Array_2'>
    >>> names = CharPArr("AVeryLongName", "Name")
    >>> names, names[0], names[1]
    (<__main__.c_char_p_Array_2 object at 0x7f39bc03c5f0>, 'AVeryLongName', 'Name')
    

@ EDIT0

添加了 Python 2 变体

答案 1 :(得分:-1)

这就是我最终实现的方式,并且似乎可以在Python 2.7中使用。

示例C文件:

void sam_test(char const *const names[],int n)
{
 int i;
   for (i = 0; i < n; i++) {
     printf ("%s \n", (names[i]));
   }
}

Python:

import ctypes
lib = ctypes.cdll['./test.so']
sam = lib['sam_test']
String = ctypes.c_char_p * 3
ii = String("First", "Second", "Third")
name = ctypes.cast(ii, ctypes.POINTER(ctypes.c_char_p))
sam(name, 3)