MrSwordFish
MrSwordFish

Reputation: 61

Python ctypes usage passing pointers

I am trying to call functions from a C library in python 2.7. I am rather confused by most tutorials or information I've found so far.

The C function takes in 3 doubles (labeled h, k, l) and 2 pointers to a double (*p, *q) to iteratively solve the two doubles, initialized with 0.0 for simplicity. The function returns nothing, it just uses the pointers to modify the values of p and q.

My current code reads:

import ctypes
path = '/foo/bar.so'
_lib = ctypes.CDLL(path)
_lib.solve.argtypes = (ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double))

def py_solve(h, k, l):
    global _lib
    p, q = ctypes.c_double(0.0), ctypes.c_double(0.0)
    _lib.solve(ctypes.c_double(h), ctypes.c_double(k), ctypes.c_double(l), ctypes.POINTER(p), ctypes.POINTER(q))
    return float(p), float(q)

I get:

'TypeError: must be a ctypes type'

on the line calling _lib.solve(...) in my py_solve function. Maybe this would be simpler by using ctypes' byref() function but I am unsure how to do that as well. Any help is appreciated, thanks.

Upvotes: 5

Views: 13370

Answers (1)

Paul Cornelius
Paul Cornelius

Reputation: 10906

The function ctypes.POINTER takes an argument that is a ctypes type. When you use it in the line

_lib.solve.argtypes = (ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double))

that's exactly what you're doing, since ctypes.c_double is a type.

When later you call it like this:

ctypes.POINTER(p)

the argument isn't a type but an instance of a type - an already initialized variable of type ctypes.c_double.

All you need to do is to create a pointer to the already initialized variables p and q. Just replace ctypes.POINTER(p) with ctypes.byref(p).

Upvotes: 8

Related Questions