ctypes指向结构的指针作为没有成员访问权限的标识符

ctypes指向结构的指针作为没有成员访问权限的标识符

本文介绍了Python ctypes指向结构的指针作为没有成员访问权限的标识符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个不同的C函数,我想将它们与Python中的ctypes一起使用.

I have two different C functions and I would like to use them with ctypes in Python.

一个函数正在建立连接并返回指向truct的指针.指针应在第二个函数中用作自变量,以重用已建立的连接.

One function is establishing a connection and returns a pointer to an truct. The pointer shall be used as an argument in the second function to reuse the established connection.

C代码:

customStruct * connect()
{
    customStruct *obj = connection_helper();
    return obj;
}

void foo(customStruct * obj)
{
    foo_helper(obj);
}

Python代码:

from ctypes import *
lib = CDLL("./test.dll")

obj = lib.connect()
lib.foo(obj)

不幸的是,当我调用 lib.foo()时,我检索到访问冲突错误.我可以使用具有 _fields _ 属性的类在Python中重新创建 customStruct 结构,但是由于该结构包含许多其他结构,并且由于我不想访问该结构作为Python本身的成员,我正在考虑如何创建可重复使用的标识符的另一种方法.

Unfortunately, I retrieve access violation errors when I call lib.foo(). I could recreate the customStruct struct in Python using a class with the _fields_ attribute, but since the struct consists of many other structs and since I don't want to access the struct members in Python itself, I'm thinking about an alternative how to create an identifier that can be reused.

我可以根据需要更改 connect()以及 foo()的定义.如果可以让我不必在python中重新创建该结构,我还可以创建另一个标识符"结构.

I can change the definition of connect() as well as foo() as I'd like. I could also create another "identifier" struct if that would allow me to not have to recreate the struct in python.

更新:看来我必须使用功能 byref()来实现我想要的功能. https://docs.python.org/3/library/ctypes.html#ctypes.byref

Update:It looks like I have to use the function byref() to achieve what I want.https://docs.python.org/3/library/ctypes.html#ctypes.byref

文档指出返回的对象只能用作外部函数调用参数",但是我不确定在 connect()中返回什么.

The documentation states "The returned object can only be used as a foreign function call parameter" but I am not sure what to return in connect() then.

推荐答案

如果您具有不透明的结构(您不知道其成员,或者不希望了解其成员),则仍应创建一个类来表示该类python中的struct.然后,您可以使用此类来正确键入您的函数.这将有助于防止错误地将错误的对象作为"CustomStruct"指针传递给错误对象.

If you have an opaque structure (you do not know its members, or do not want to know its members), you should still create a class to represent that struct in python. You can then use this class to properly type your functions. This will help prevent bugs where you accidentally pass the wrong object as a "CustomStruct" pointer.

例如:

from ctypes import cdll, c_int, c_void_p

mylib = cdll.LoadLibrary('mylib')

class CustomStructP(c_void_p):
    # subclassing c_void_p creates an opaque pointer type that is distinct
    # from c_void_p, and can only be instantiated as a pointer
    pass

create = mylib.create
create.argtypes = [c_int]
create.restype = CustomStructP

display = mylib.display
display.argtypes = [CustomStructP]
display.restype = None

delete = mylib.delete
delete.argtypes = [CustomStructP]
delete.restype = None

obj = create(10)
display(obj)
delete(obj)

display(CustomStructP())  # passing a null pointer

现在,如果您尝试以下操作: display(c_void_p()),您将得到:

Now, if you tried something like: display(c_void_p()), you would get:

Traceback (most recent call last):
  File "C:\Users\User\Documents\python\src\main.py", line 31, in <module>
    display(c_void_p())
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type

我使用的C代码是:

#include <stdio.h>
#include <stdlib.h>

struct customStruct {
    int val;
};

struct customStruct *
create(int val) {
    struct customStruct *obj = malloc(sizeof(struct customStruct));
    obj->val = val;
    return obj;
}

void
display(struct customStruct *obj) {
    if (obj) {
        printf("customStruct(%d) @ %p\n", obj->val, obj);
    }
    else {
        puts("customStruct is NULL");
    }
}

void
delete(struct customStruct *obj) {
    free(obj);
}

这篇关于Python ctypes指向结构的指针作为没有成员访问权限的标识符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 05:55