从 C 返回 CTypes 指针

发布于 2024-10-09 19:56:52 字数 443 浏览 3 评论 0原文

我正在编写一个 Python C 扩展,它需要返回一个指向内存中 char 数组的 CTypes 指针(我需要与另一个需要 CTypes 指针的 Python 库进行交互)。

我找不到有关 C 的任何类型的 CTypes 接口的任何文档。是否有任何解决方法,例如调用 Python 指针构造函数?

static PyObject *get_pointer(myObject *self)
{
    char *my_pointer = self->internal_pointer;
    return PyCTypes_Pointer(my_pointer); /* how do I turn 'my_pointer' into 
              a Python object representing a CTypes pointer? */
}

提前致谢。

I'm writing a Python C Extension that needs to return a CTypes pointer to a char array in memory (I need to interface with another Python library that expects a CTypes pointer).

I cannot find any documentation on any kind of CTypes interface for C. Are there any workarounds, like calling the Python pointer constructor?

static PyObject *get_pointer(myObject *self)
{
    char *my_pointer = self->internal_pointer;
    return PyCTypes_Pointer(my_pointer); /* how do I turn 'my_pointer' into 
              a Python object representing a CTypes pointer? */
}

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

揪着可爱 2024-10-16 19:56:52

即使您使用 C 语言编程,也请尝试使用 Python 本身。遗憾的是我不知道 C 的任何类型的 CTypes 接口,并且在源代码中找不到任何提示。也许您可以使用以下代码编写自己的 PyCTypes_Pointer 方法。

我没有在这里进行任何清理、错误检查或处理,但它对我来说适用于 Python 2.7 和 3.4。

#include <Python.h>

static const char *test = "Testing Python ctypes char pointer ..."; 

static PyObject *c_char_p = NULL;
static PyObject *c_void_p = NULL;
static PyObject *cast = NULL;

static PyObject * char_p ( void ) {
    PyObject *p = PyLong_FromVoidPtr((void *) test);
    p = PyObject_CallFunction(c_void_p, "O", p);
    return PyObject_CallFunction(cast, "OO", p, c_char_p);
}

static PyObject *len ( void ) {
    return PyLong_FromSize_t(strlen(test));
}

static PyMethodDef methods[] = {
    {"char_p", (PyCFunction) char_p, METH_NOARGS, ""},
    {"len", (PyCFunction) len, METH_NOARGS, ""},
    { NULL }
};

#if PY_MAJOR_VERSION >= 3
static PyModuleDef module = {PyModuleDef_HEAD_INIT, "pyt", "", -1, methods,
    NULL, NULL, NULL, NULL};
#define INIT_FUNC PyInit_pyp
#else
#define INIT_FUNC initpyp
#endif

PyMODINIT_FUNC INIT_FUNC ( void ) {
    PyObject* m;

    PyObject *ctypes = PyImport_ImportModule("ctypes");
    PyObject *c_char = PyObject_GetAttrString(ctypes, "c_char");
    c_char_p = PyObject_CallMethod(ctypes, "POINTER", "O", c_char);
    c_void_p = PyObject_GetAttrString(ctypes, "c_void_p");
    cast = PyObject_GetAttrString(ctypes, "cast");

#if PY_MAJOR_VERSION >= 3
    m = PyModule_Create(&module);
#else
    m = Py_InitModule("pyp", methods);
#endif

    return (PyMODINIT_FUNC) m;
}

只需构建

from __future__ import print_function
from distutils.core import Extension, setup
import sys
sys.argv.extend(["build_ext", "-i"])
setup(ext_modules = [Extension('pyp', ['pyp.c'])])
import pyp
c = pyp.char_p()
print(c[:pyp.len()])

并获得类似的输出

<class 'ctypes.LP_c_char'> Testing Python ctypes char pointer ...

如果您仅处理以零结尾的字符串,您可能可以直接使用 ctypes.c_char_p ,也许......

Even though you're programming in C, try using Python itself. Sadly I don't know of any kind of CTypes interface for C and couldn't find any hint in the sources. Maybe you'll be able to write your own PyCTypes_Pointer method with the following.

I didn't do any cleanup, error checking or handling here, but it's working with Python 2.7 and 3.4 for me.

#include <Python.h>

static const char *test = "Testing Python ctypes char pointer ..."; 

static PyObject *c_char_p = NULL;
static PyObject *c_void_p = NULL;
static PyObject *cast = NULL;

static PyObject * char_p ( void ) {
    PyObject *p = PyLong_FromVoidPtr((void *) test);
    p = PyObject_CallFunction(c_void_p, "O", p);
    return PyObject_CallFunction(cast, "OO", p, c_char_p);
}

static PyObject *len ( void ) {
    return PyLong_FromSize_t(strlen(test));
}

static PyMethodDef methods[] = {
    {"char_p", (PyCFunction) char_p, METH_NOARGS, ""},
    {"len", (PyCFunction) len, METH_NOARGS, ""},
    { NULL }
};

#if PY_MAJOR_VERSION >= 3
static PyModuleDef module = {PyModuleDef_HEAD_INIT, "pyt", "", -1, methods,
    NULL, NULL, NULL, NULL};
#define INIT_FUNC PyInit_pyp
#else
#define INIT_FUNC initpyp
#endif

PyMODINIT_FUNC INIT_FUNC ( void ) {
    PyObject* m;

    PyObject *ctypes = PyImport_ImportModule("ctypes");
    PyObject *c_char = PyObject_GetAttrString(ctypes, "c_char");
    c_char_p = PyObject_CallMethod(ctypes, "POINTER", "O", c_char);
    c_void_p = PyObject_GetAttrString(ctypes, "c_void_p");
    cast = PyObject_GetAttrString(ctypes, "cast");

#if PY_MAJOR_VERSION >= 3
    m = PyModule_Create(&module);
#else
    m = Py_InitModule("pyp", methods);
#endif

    return (PyMODINIT_FUNC) m;
}

Just build with

from __future__ import print_function
from distutils.core import Extension, setup
import sys
sys.argv.extend(["build_ext", "-i"])
setup(ext_modules = [Extension('pyp', ['pyp.c'])])
import pyp
c = pyp.char_p()
print(c[:pyp.len()])

and get an output like

<class 'ctypes.LP_c_char'> Testing Python ctypes char pointer ...

If you're handling zero-terminated strings only, you might be able to use ctypes.c_char_p directly, maybe ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文