Вопрос

I'm trying to use a C library (libmms, although that's not really important) with ctypes; I wrote a small working C program first, but I seem to be having difficulty getting it to work with ctypes

Whenever I specify the return type (which is required, for I need it later) using test.restype = custom_t things start to break.

My arguments (url in specific) don't seem to work, or work very strangely (see the comments in C file). If I reduce the struct to just one entry (int a) everything works as expected! (It breaks at about 3 or 4 lines, the original struct from libmms is much larger).

I've (obviously) tried adding argtypes, muck about with various datatypes, etc., all to no avail...

Some simple example code to demonstrated the problem:

C library:

// Compiled with: clang -shared -Wl,-soname,test -o test.so -fPIC test.c
// Also tried gcc, with the same results
#include <stdio.h>

struct mmsh_t {
    int a;
    int b;
    int c;
    int d;
    int e;
};

// Called as: test(None, None, b'Hello', 42)
// Outputs: mmsh_connect: (null)
struct mmsh_t *mmsh_connect (void *io, void *data, const char *url, int bandwidth) {

// Called as: test(42, b'Hello')
// Segfaults
// Curiously, when I output this with the Python code:
// test(b'Hello')
// It outputs:  mmsh_connect: Hello
// Which is what I expected!
//struct mmsh_t *mmsh_connect (int io, const char *url) {

// Called as: test(b'Hello')
// Outputs: mmsh_connect: 
//struct mmsh_t *mmsh_connect (const char *url) {
    struct mmsh_t *this;
    printf("mmsh_connect: %s\n", url);
    return this;
}

Python code:

#!/usr/bin/env python3
# Python2 give the same results

import ctypes

class custom_t(ctypes.Structure):
    _fields_ = [
        ('a', ctypes.c_int),
        ('b', ctypes.c_int),
        ('c', ctypes.c_int),
        ('d', ctypes.c_int),
        ('e', ctypes.c_int),
    ]

lib = ctypes.cdll.LoadLibrary('./test.so');
test = lib.mmsh_connect
test.restype = custom_t # <- Oh woe is this line!

test(None, None, b'Hello', 42)
#test(42, b'Hello')
#test(b'Hello')

What am I missing / doing wrong?

Это было полезно?

Решение

The function returns a pointer to a structure, not a structure.

test.restype = ctypes.POINTER(custom_t)

Also you need to declare the arguments to the function:

lib.mmsh_connect.argtypes = [c_void_p, c_void_p, c_char_p, c_int]

Usage:

s = lib.mmsh_connect(None, None, 'Hello', 42)
print ctypes.c_value(s.contents.a)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top