Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python C类型更改结构值_Python_C_Ctypes - Fatal编程技术网

Python C类型更改结构值

Python C类型更改结构值,python,c,ctypes,Python,C,Ctypes,这是我的C代码: typedef struct { int a; }A; __declspec(dllexport) A new_a(int x) { A a = {x}; return a; } __declspec(dllexport) void change(A a) { a.a++; } __declspec(dllexport) int get_a (A a) { return a.a; } 我将其编译成模块DLL,并在Python中执行以下操作: im

这是我的C代码:

typedef struct {
    int a;
}A;

__declspec(dllexport) A new_a(int x) {
    A a = {x};
    return a;
}

__declspec(dllexport) void change(A a) { a.a++; }

__declspec(dllexport) int get_a (A a) { return a.a; }
我将其编译成模块DLL,并在Python中执行以下操作:

import ctypes

lib = ctypes.windll.LoadLibrary('C:\\Users\\avishah\\CLionProjects\\Math\\lib\\libpythonclass2.dll')

a = lib.new_a(10)
print(lib.get_a(a), type(a))  # gives 10, says type of a is 'int'
lib.change(a)  # doesn't change value
print(lib.get_a(a))  # still shows 10
我确信我必须在C代码中使用指针,但它通常会给我以下错误:

OSError: exception: access violation reading 0x000000000000000A

您的代码有两个问题

首先,您没有为导入的FFI函数指定类型签名。您需要为结构创建类型定义,并为导入的函数指定参数和返回类型

导入ctypes
lib=ctypes.windell.LoadLibrary(r'C:\Users\avishah\CLionProjects\Math\lib\libpythonclass2.dll')
A类(ctypes.Structure):
_字段=(
('a',ctypes.c_int),
)
new_a=lib.new_a
new_a.restype=a
new_a.argtypes=(ctypes.c_int,)
change=lib.change
change.restype=None
change.argtypes=(A,)
get_a=lib.get_a
get_a.restype=ctypes.c_int
获取_a.argtypes=(a,)
第二个是
change
函数按值接收结构。换句话说,函数对参数列表上接收到的结构副本进行操作,这意味着调用方持有的副本永远不会被修改。要实际修改结构,需要传递一个指针:

\uuuu declspec(dllexport)void change(A*A){A->A++}
change=lib.change
change.restype=None
change.argtypes=(ctypes.POINTER(A),)
现在,您的代码应该按照预期的方式运行:

a=new_a(10)
打印(获取a(a),键入(a))#应打印10
变更(ctypes.byref(a))#相当于C:变更(&a);
打印(获取a(a))#应打印11

谢谢!这真的很有帮助。。。我很难理解这一点,因为大多数人都以Linux为例,而这一切都不存在。一个问题。。。它是否真的因为使用指针而对内存使用有所帮助,或者它仍然在内部创建副本?Linux需要相同的类型声明,在不同的平台之间实际上没有区别。考虑到该结构只是一个
int
,从技术上讲,遍历指针可能会增加这里的内存使用量(虽然不会增加太多)。但是,随着结构的增长,将其作为指针传递将在内存使用方面获得更多回报。无论哪种方式,都没有复制:将指针作为参数传递的全部目的是允许被调用方对调用方拥有的完全相同的对象进行操作,而不是复制。