2017-05-24 69 views
0

私はCtypesを通して呼び出すCライブラリ(clibとヘッダclib.h)を持っています。 get_structは、構造体Fooへのポインタを返します。このポインタは、clib.hで前方宣言されていて、他の関数呼び出しのためにポインタとして使用できます(use_struct(Foo* foo)など)。私はCythonで同じ関数コードを呼び出すために、このポインタを使用したいと思います。ctypes構造体をcythonに渡す

私は構造の内容を知らないので、私はcythonで重複した構造を作り、ctypes構造の値をコピーすることはできません。だから私は代わりに、同じAPIをバインドするいくつかのCコードを呼び出すために同じメモリ空間へのcythonポインタを作成したいと思います。

コードはおおよそこれを行っています。

cdef extern from "clib.h": 
    cdef struct Foo: 
     pass 

    void use_struct(Foo *) 


cpdef bar(foo_ct): 

    cdef Foo* foo_cy 
    foo_cy = <Foo*>&foo_ct # or something equivalent 
    cy_use_struct(foo_cy) 

Cythonについて:cylib.pyxでCython側で

# load clib DLL 
clib = ctypes.CDLL('clib.so') 

# empty Ctypes declaration 
class Foo_ct(ctypes.Structure): 
    pass 

# get and use the struct 
clib.get_struct.restype = ctypes.POINTER(Foo_ct) 
foo_ct = clib.get_struct() 
clib.use_struct(foo_ct) 

# call cython code 
bar(foo_ct) 

typedef struct Foo Foo; 
Foo * get_struct(); 
void use_struct(Foo *) 

のctypesとPythonの側:clib.hで

側、in cylibc.cpp:

#import "clib.h" 

void cy_use_struct(Foo * foo) 
{ 
    use_struct(foo); 
} 

foo_cy = <Foo*>&foo_ctCannot take address of Python variableまたはassigning to 'PyObject *' (aka '_object *') from incompatible type 'void'のいずれかを作成して返しません。

今後の予定はありますか?

+0

foo_ct'は 'Foo_ct'構造体のアドレスである'ので、あなたはこの 'バー(size_tのfoo_ct)を行うことができます。 cy_use_struct ( foo_ct) 'です。つまり、CオブジェクトのアドレスをPythonで取得し、Cオブジェクトのcythonでキャストします。 – oz1

+0

これは良いアイデアですが、これは私にセグメンテーションフォルトを与えます.. – toine

+2

私は現在これをテストすることができませんので、私はコメント:私はアドレスを取得する 'ctypes.addressof(foo_ct)'を行うと思います。それをCythonの整数にキャストしてからポインタにキャストします。 (私はかなり2ステップのキャストが必要だと確信している) – DavidW

答えて

0

@ OZ1と@DavidWコメント、以下の作品に基づく:

from libc.stdint cimport uintptr_t 
cdef uintptr_t adr = <uintptr_t>ctypes.addressof(foo_ct.contents) 
cy_use_struct(<Foo*>adr) 
+2

整数としてのポインタは 'uintptr_t'であり、' long'ではありません。これは、64ビットWindowsや、32ビットの「long」型の他の64ビットプラットフォーム上のアドレスを切り捨てることになります。 – eryksun

関連する問題