5

PythonプログラムをCライブラリとインターフェースする必要があります。呼び出す必要のある特定の関数は配列を取り、doubleを返します。次の関数は同じシグネチャを持ち、私自身の関数よりも理解しやすいです。

double sum(double * array, const int length) {
 double total = 0;
 int i;
 for (i=0; i<length; i++) {
     total += array[i];
 }
 return total;
}

私の現在の解決策は次のとおりです。

import ctypes
lib = ctypes.CDLL(library_name) 

l = 10
arr = tuple(range(l))

lib.sum.restype = ctypes.c_double
values = (ctypes.c_double * l)(*arr)
ret = lib.sum(values, l)

しかし、私は自分のコードで配列モジュールを頻繁に使用しており、Cコードでそれらを使用することは、型付き配列であるため、より簡単であるように思われました。そこで、C関数に配列を直接フィードしようとしましたが、機能しませんでした。それを機能させるために、私は次のように配列をラップしました:

class Array(array):

   @property
   def _as_parameter_(self):
      return (TYPES[self.typecode] * len(self))(*self)

ここで、TYPESは、タイプコードを配列からctypesタイプにマップします。

   TYPES = {'c': ctypes.c_char,
            'b': ctypes.c_byte,
            'B': ctypes.c_ubyte,
            '?': ctypes.c_bool,
            'h': ctypes.c_short,
            'H': ctypes.c_ushort,
            'i': ctypes.c_int,
            'I': ctypes.c_uint,
            'l': ctypes.c_long,
            'L': ctypes.c_ulong,
            'q': ctypes.c_longlong,
            'Q': ctypes.c_ulonglong,
            'f': ctypes.c_float,
            'd': ctypes.c_double}

_as_parameter_を別の配列を作成しないものに置き換える方法はありますか?

ありがとう

4

2 に答える 2

4

use array.buffer_info() to get the address and length, and cast() the address to POINTER(c_double):

from array import array
buf = array("d", range(101))
addr, count = buf.buffer_info()
print lib.sum(cast(addr, POINTER(c_double)), count)
于 2012-05-17T00:56:00.523 に答える
0

これがより良い答えであるというわけではありませんが、完全を期すために、 numpyを使用している場合は、numpyがキャスト部分を処理できるため、少し異なります。

import numpy as np
data = np.arange(101, dtype=ctypes.c_double) # making this match seems important sometimes
print lib.sum(data.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), len(data))
于 2012-06-05T01:53:09.523 に答える