我是靠谱客的博主 威武盼望,最近开发中收集的这篇文章主要介绍python const char_[转] python关于ctypes使用char指针与bytes相互转换的问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

最近研究人脸识别,需要用python调用so动态库,涉及到c/c++中的指针字符串转Python的bytes对象的问题。

按照ctypes的文档,直观方式是先创建对应的类型数组,再将指针取地址一一赋值:

from ctypes import *

p=(c_char * 10)()

for i in range(10):

p[i] = i

b=bytes(bytearray(p))

print(b)

from ctypes import * p=(c_char * 10)() for i in range(10): p[i] = i b=bytes(bytearray(p)) print(b)

搜寻了各种资料,都未能找到更好的。。。直到ctypes.string_at

_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)

def string_at(ptr, size=-1):

"""string_at(addr[, size]) -> string

Return the string at addr."""

return _string_at(ptr, size)

_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) def string_at(ptr, size=-1): """string_at(addr[, size]) -> string Return the string at addr.""" return _string_at(ptr, size)

于是char*转bytes可以直接用string_at方法,传入指针地址,以及字符串长度即可。

同样的问题,bytes对象需要传给c/c++代码。。。

直观方式同样是创建char数组array,拷贝bytes之后,再用cast强制转换成c_char_p

from ctypes import *

p=(c_char * 10)()

for i in range(10):

p[i] = i

m=cast(p, c_char_p)

print(m)

from ctypes import * p=(c_char * 10)() for i in range(10): p[i] = i m=cast(p, c_char_p) print(m)

比较奇葩的是cast得到的对象,如果我们直接用bytes对象cast。。。

from ctypes import *

b=b'0123456789'

m=cast(p, c_char_p)

print(m)

from ctypes import * b=b'0123456789' m=cast(p, c_char_p) print(m)

吼吼,奇迹出现了,bytes对象cast成了char*指针。。。用string_at转换看看

string_at(m)

string_at(m)

总结一下:

1、bytes基于Buffer Protocol,查看其c实现https://hg.python.org/cpython/file/3.4/Objects/bytesobject.c

2、string_as的c代码https://hg.python.org/cpython/file/3717b1481d1b/Modules/_ctypes/_ctypes.c

static PyObject *

string_at(const char *ptr, int size)

{

if (size == -1)

return PyString_FromString(ptr);

return PyString_FromStringAndSize(ptr, size);

}

static PyObject * string_at(const char *ptr, int size) { if (size == -1) return PyString_FromString(ptr); return PyString_FromStringAndSize(ptr, size); }

3、cast的c代码同样在_ctypes.c(https://hg.python.org/cpython/file/3717b1481d1b/Modules/_ctypes/_ctypes.c)

static PyObject *

cast(void *ptr, PyObject *src, PyObject *ctype)

{

CDataObject *result;

if (0 == cast_check_pointertype(ctype))

return NULL;

result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL);

if (result == NULL)

return NULL;

/*

The casted objects '_objects' member:

It must certainly contain the source objects one.

It must contain the source object itself.

*/

if (CDataObject_Check(src)) {

CDataObject *obj = (CDataObject *)src;

/* CData_GetContainer will initialize src.b_objects, we need

this so it can be shared */

CData_GetContainer(obj);

/* But we need a dictionary! */

if (obj->b_objects == Py_None) {

Py_DECREF(Py_None);

obj->b_objects = PyDict_New();

if (obj->b_objects == NULL)

goto failed;

}

Py_XINCREF(obj->b_objects);

result->b_objects = obj->b_objects;

if (result->b_objects && PyDict_Check(result->b_objects)) {

PyObject *index;

int rc;

index = PyLong_FromVoidPtr((void *)src);

if (index == NULL)

goto failed;

rc = PyDict_SetItem(result->b_objects, index, src);

Py_DECREF(index);

if (rc == -1)

goto failed;

}

}

/* Should we assert that result is a pointer type? */

memcpy(result->b_ptr, &ptr, sizeof(void *));

return (PyObject *)result;

failed:

Py_DECREF(result);

return NULL;

}

static PyObject * cast(void *ptr, PyObject *src, PyObject *ctype) { CDataObject *result; if (0 == cast_check_pointertype(ctype)) return NULL; result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL); if (result == NULL) return NULL; /* The casted objects '_objects' member: It must certainly contain the source objects one. It must contain the source object itself. */ if (CDataObject_Check(src)) { CDataObject *obj = (CDataObject *)src; /* CData_GetContainer will initialize src.b_objects, we need this so it can be shared */ CData_GetContainer(obj); /* But we need a dictionary! */ if (obj->b_objects == Py_None) { Py_DECREF(Py_None); obj->b_objects = PyDict_New(); if (obj->b_objects == NULL) goto failed; } Py_XINCREF(obj->b_objects); result->b_objects = obj->b_objects; if (result->b_objects && PyDict_Check(result->b_objects)) { PyObject *index; int rc; index = PyLong_FromVoidPtr((void *)src); if (index == NULL) goto failed; rc = PyDict_SetItem(result->b_objects, index, src); Py_DECREF(index); if (rc == -1) goto failed; } } /* Should we assert that result is a pointer type? */ memcpy(result->b_ptr, &ptr, sizeof(void *)); return (PyObject *)result; failed: Py_DECREF(result); return NULL; }

最后

以上就是威武盼望为你收集整理的python const char_[转] python关于ctypes使用char指针与bytes相互转换的问题的全部内容,希望文章能够帮你解决python const char_[转] python关于ctypes使用char指针与bytes相互转换的问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部