zoukankan      html  css  js  c++  java
  • [转] 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)

    搜寻了各种资料,都未能找到更好的。。。直到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)

    于是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)

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

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

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

    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);
    }

    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;
    }
  • 相关阅读:
    3星|《腾讯产业森林:AI时代的创业密码》:后半部分是较详细的创业指南,前面泛泛介绍腾讯、AI
    3星|《三联生活周刊》2017年49期:小孩子一般在3岁时开始学会说“黑色”谎言,也就是专门利己毫不利人的谎言
    VS2010调试 --指南 Reference from : http://blog.csdn.net/kingzone_2008/article/details/8133048
    画图------Brush
    JavaScript Function.apply() 函数详解
    window.addEventListener来解决让一个js事件执行多个函数
    C# 框架是什么?MVC是什么 ?工厂模式是什么?设计模式是什么?三层架构是什
    C#反射机制介绍
    javascript 小日历
    javascript里的post和get有什么区别
  • 原文地址:https://www.cnblogs.com/hjbf/p/11969521.html
Copyright © 2011-2022 走看看