【问题标题】:Python Ctypes passing a structure pointer defined in .h file.Python Ctypes 传递在 .h 文件中定义的结构指针。
【发布时间】:2018-12-17 18:57:22
【问题描述】:

我是 ctypes 和 C 的新手,并且无法通过 ctypes 将结构指针变量传递给在 python 中调用的 c 函数。如果它太基本和明显,请多多包涵。 下面是我的 c 代码的样子。

#include "mylib.h"   (inside this mylib.h file MYSTRUCT is defined)

struct MYSTRUCT* modifystruct(a,b,c,d,e)
{
MYSTRUCT *mystpointer;
.....
.....
return mystpointer;
} 


int mycfunction(mystpointer)
MYSTRUCT *mystpointer;
{
.........
.........
.........
}

和上面一样,修改结构函数更新 *mystpointer 这是一个指向 MYSTRUCT 的指针并返回它。 而mycfunction就是传递返回的mystpointer。在 C 中,这在 main 函数中运行良好。 但是当我尝试使用 ctypes 将“.so”文件加载到 python 中时,它失败了,我认为我没有正确定义 mystpointer 的 argtype。 下面是我写的简短的python代码。假设上面的 c 代码被编译为“mycmodule.so”。

mylib=cdll.LoadLibrary("mycmodule.so")
mycfunction=mylib.mycfunction
mycfunction.restype=c_int
mycfunction.argtypes=[c_void_p]
mystpointer=c_void_p()

在 C 代码中,我必须将 mystpointer 类型定义为“MYSTRUCT *mystpointer;” 但是,我不知道如何在 ctypes 中这样做......相反,我将类型定义为 c_void_p 但这会触发失败。提前致谢!

【问题讨论】:

  • 在 C 中,没有在代码中为 modifystruct() 声明参数类型...除此之外,结构在哪里分配?例如,除了 modifystruct() 之外,是否还有另一个 C 函数返回指向您的结构的指针?或者您是否尝试通过 Python 代码为结构分配内存?

标签: python c pointers struct ctypes


【解决方案1】:

我认为您可能缺少的是确切地知道您想要分配结构内存的位置。下面的 c 代码提供了一个为结构分配内存并返回指向它的指针的函数(new_struct())。

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

typedef struct {
    int a;
    int b;
} my_struct;

my_struct *new_struct()
{
    my_struct *struct_instance = (my_struct *)malloc(sizeof(my_struct));
    memset(struct_instance, 0, sizeof(my_struct));
    return struct_instance;
}

int modify_struct(my_struct *ms) {
    ms->a = 1;
    ms->b = 2;
    return 0;
}

void print_struct_c(my_struct *ms) {
    printf("my_struct {\n"
           "    a = %d\n"
           "    b = %d\n"
           "}\n", ms->a, ms->b);
}

从 Python 中,要获取指针,请调用执行分配的 C 函数,然后您可以将其传递给其他将其作为参数的 C 函数。

import ctypes

lib_file_path = <<< path to lib file >>>

# Very simple example of how to declare a ctypes structure to twin the
# C library's declaration. This doesn't need to be declared if the Python
# code isn't going to need access to the struct's data members.
class MyStruct(ctypes.Structure):
    _fields_ = [('a', ctypes.c_int),
                ('b', ctypes.c_int)]

def print_struct(s):
    # Print struct that was allocated via Python ctypes.
    print("my_struct.a = %d, my_struct.b = %d" % (s.a, s.b))

def print_struct_ptr(sptr):
    # Print pointer to struct. Note the data members of the pointer are 
    # accessed via 'contents'.
    print("my_struct_ptr.contents.a = %d, my_struct_ptr.contents.b = %d" 
          % (sptr.contents.a, sptr.contents.b))


my_c_lib = ctypes.cdll.LoadLibrary(lib_file_path)

# If you don't need to access the struct's data members from Python, then 
# it's not necessary to declare MyStruct above. Also, in that case,
# 'restype' and 'argtypes' (below) can be set to ctypes.c_void_p instead.
my_c_lib.new_struct.restype     =  ctypes.POINTER(MyStruct)
my_c_lib.modify_struct.argtypes = [ctypes.POINTER(MyStruct)]

# Call C function to create struct instance.
my_struct_c_ptr = my_c_lib.new_struct()
print_struct_ptr(my_struct_c_ptr)

my_c_lib.modify_struct(my_struct_c_ptr)
print_struct_ptr(my_struct_c_ptr)

# Allocating struct instance from Python, then passing to C function.
my_struct_py = MyStruct(0, 0)
print_struct(my_struct_py)

my_c_lib.modify_struct(ctypes.byref(my_struct_py))
print_struct(my_struct_py)

# Data members of Python allocated struct can be acessed directly.
my_struct_py.a = 555

my_c_lib.print_struct_c(ctypes.byref(my_struct_py)) # Note use of 'byref()'
                                                    # to invoke c function.

上面的代码已经更新,包含一个示例,说明如何通过 Python 分配结构实例,以及如何访问 C 分配或 Python 分配的结构的数据成员(注意打印函数的差异)。

【讨论】:

  • 感谢您的提示!我试过你的例子。我能够运行 (int mycfunction(mystpointer)) 函数,但它没有给我正确的结果。你能分享一下如何从 Python 分配和访问结构吗?
  • 更新了更多示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-09
  • 1970-01-01
  • 2017-01-22
  • 2014-01-28
  • 1970-01-01
  • 2012-05-16
  • 1970-01-01
相关资源
最近更新 更多