最近研究人脸识别,需要用python调用so动态库,涉及到c/c++中的指针字符串转Python的bytes对象的问题。
按照ctypes的文档,直观方式是先创建对应的类型数组,再将指针取地址一一赋值:

from ctypes import *
  
p=(c_char * )()
for i in range():
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=-):
"""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 * )()
for i in range():
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 == -)
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 ( == 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 == -)
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关于ctypes使用char指针与bytes相互转换的问题的更多相关文章

  1. 初始化char指针--赋值和strcpy() 本质区别【转】

    原文地址:http://hi.baidu.com/todaygoodhj/item/0500b341bf2832e3bdf45180 使用常量字符串初始化char指针,或者使用strcpy复制,从语法 ...

  2. char[]数组与char *指针的区别

    char[]数组与char *指针的区别 问题描述 虽然很久之前有看过关于char指针和char数组的区别,但是当时没有系统的整理,到现在频繁遇到,在string,char[], char *中迷失了 ...

  3. char指针

    1.在C语言中,没有字符串类型,因此使用char指针表示字符串. 2.那么问题来了,使用char* 表示字符串,到哪里是结尾呢?因此需要一个特殊的字符作为哨兵,类似迭代器中的end(),这个哨兵就是' ...

  4. char数组与char指针

    1.以字符串形式出现的,编译器会在结尾自动添加\0,思考,为什么? 存在的C语言方法,如strlen(s),计算字符串的长度,其中s指针.strlen要计算字符串长度,必须知道哪里是结尾,因此使用\0 ...

  5. C: 当字符数组首指针转化成char *指针,sizeof(*ptr)不为array的size

    #include <stdio.h> #include <string.h> int main() { char a[10] = "\0"; char *p ...

  6. char 指针如何判断字符串需要输出长度

    先上代码: #include <stdio.h> #include <string.h> ] = "; int func1(const char *ip) { pri ...

  7. C++中将对象this转换成unsigned char指针

    示例程序 // ---CodeBlob.h--- #ifndef CODEBLOB_H_ #define CODEBLOB_H_ class CodeBlob { private: const cha ...

  8. Java之byte、char和String类型相互转换

    package basictype; /** * byte.char和String类型相互转换 */ public class CHJavaType { public static void main ...

  9. python pip 'nonetype' object has no attribute 'bytes'

    python pip 'nonetype' object has no attribute 'bytes' 更新 pip for Windows : python -m pip install -U ...

随机推荐

  1. 模板 - Floyd

    void Floyd(){ for(int k = 1; k <= n; ++k) { for(int i = 1; i <= n; ++i) { for(int j = 1; j < ...

  2. GitHub入门使用

    1.首先注册账号. 2.新建仓库. 3.安装GitBash 4.首先要在本地创建一个ssh key. $ ssh -keygen -t rsa -C "your email@.com&quo ...

  3. vue-cli proxyTable中跨域中pathRewrite 解释

      问:proxyTable 里面的pathRewrite里面的‘^/iclient’:'' 什么意思? 答:用代理, 首先你得有一个标识, 告诉他你这个连接要用代理. 不然的话, 可能你的 html ...

  4. Linux系统性能测试工具(四)——CPU性能测试工具之super_pi、sysbench

    本文介绍关于Linux系统(适用于centos/ubuntu等)的CPU性能测试工具-sysbench.CPU性能测试工具包括: super_pi: sysbench——不仅可以测试CPU性能,而且可 ...

  5. python并发编程中的多进程(代码实现)

    一.multipricessing模块的介绍 python中的多线程无法利用多核优势,如果想要充分的使用多核CPU资源,在python中大部分情况下需要用多线程,python提供了multiproce ...

  6. dockerfile制作笔记

    dockerfile语法格式:   FROM: 基础镜像(就是在什么镜像上面做)   MAINTAINER: 镜像创建者信息(作者的信息)   EXPOSE: 开放的端口   ENV: 设置变量   ...

  7. 合肥学院ACM集训队第一届暑假友谊赛 B FYZ的求婚之旅 D 计算机科学家 F 智慧码 题解

    比赛网址:https://ac.nowcoder.com/acm/contest/994#question B FYZ的求婚之旅 思路: 然后用快速幂即可. 细节见代码: #include <i ...

  8. adam优化

    AdaGrad (Adaptive Gradient,自适应梯度) 对每个不同的参数调整不同的学习率, 对频繁变化的参数以更小的步长进行更新,而稀疏的参数以更大的步长进行更新. gt表示第t时间步的梯 ...

  9. java 中的编码(二)

    UTF-16编码规则: 按照UTF-16编码规则计算下Unicode码位为 U+10002 (十进制:65538)的字符的UTF-16编码表示. U+10002落在 [U+10000, U+10FFF ...

  10. C++ GUI Qt4学习笔记03

    C++ GUI Qt4学习笔记03   qtc++spreadsheet文档工具resources 本章介绍创建Spreadsheet应用程序的主窗口 1.子类化QMainWindow 通过子类化QM ...