2017-12-28 12 views
0

したがって、cypiを使用してpypyですぐにCライブラリにアクセスしようとしています。PYPY、CFFIインポートエラーcffiライブラリ '_heap_i'に 'initQueue'という名前の関数、定数、またはグローバル変数がありません

私は、特に私がcffiで、heapqで、純粋なPythonのプライオリティキューを比較すると、プロジェクトのためのctypesていますコマンドラインツール9.1

と私のMacProを使用しています。

私はroman10のウェブサイトから優先度キューのC実装を取得しました。

私はcffiのドキュメントに従っていますが、ライブラリの内部にある関数を呼び出そうとするとエラーが発生します。

私は5つのファイルがあります.Cプライオリティキュー、cffi heap_inter.pyとのインタフェースのpythonファイル用/ .hのcheap.ccheap.h、キューheap.pyにアクセスするためのプログラムのラッパー、およびテストスクリプトtest_heap.py

これはエラーです:私はexport CC=gccexport CC=clangと試み、また私のMPICH

pypy test_heap.py

はAttributeError:cffiライブラリ '_heap_i' は関数で、定数、またはグロブを持っていませんal変数は 'initQueue'という名前です

しかし、私は、initQueueというコンパイルされているcライブラリの関数を持っています。私が実行されたコマンドは、ここで building '_heap_i' extension clang -DNDEBUG -O2 -fPIC -I/opt/local/include -I/opt/local/lib/pypy/include -c _heap_i.c -o ./_heap_i.o cc -pthread -shared -undefined dynamic_lookup ./_heap_i.o -L/opt/local/lib -o ./_heap_i.pypy-41.so clang: warning: argument unused during compilation: '-pthread' [-Wunused-command-line-argument]

は私の源であるheap_inter.pyにpypyを呼び出す

cheap.h 

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

/* priority Queue implimentation via roman10.net */ 
struct heapData { 
    //everything from event           
    //tx string              
    char tx[64]; 
    //txID int               
    int txID; 
    //rx string              
    char rx[64]; 
    //rxID int               
    int rxID; 
    //name string              
    char name[64]; 
    //data Object              

    //time float              
    float time; 
}; 
struct heapNode { 
    int value; 
    struct heapData data;    //dummy      
}; 
struct PQ { 
    struct heapNode* heap; 
    int size; 
}; 
void insert(struct heapNode aNode, struct heapNode* heap, int size); 
void shiftdown(struct heapNode* heap, int size, int idx); 
struct heapNode removeMin(struct heapNode* heap, int size); 
void enqueue(struct heapNode node, struct PQ *q); 
struct heapNode dequeue(struct PQ *q); 
struct heapNode peak(struct PQ *q); 
void initQueue(struct PQ *q, int n); 
int nn = 1000000; 
struct PQ q; 
int main(int argc, char **argv); 

その後、heap.c

void insert(struct heapNode aNode, struct heapNode* heap, int size) { 
    int idx; 
    struct heapNode tmp; 
    idx = size + 1; 
    heap[idx] = aNode; 
    while (heap[idx].value < heap[idx/2].value && idx > 1) { 
     tmp = heap[idx]; 
     heap[idx] = heap[idx/2]; 
     heap[idx/2] = tmp; 
     idx /= 2; 
    } 
} 

void shiftdown(struct heapNode* heap, int size, int idx) { 
    int cidx;  //index for child                                                                                  
    struct heapNode tmp; 
    for (;;) { 
     cidx = idx*2; 
     if (cidx > size) { 
      break; //it has no child                                                                                  
     } 
     if (cidx < size) { 
      if (heap[cidx].value > heap[cidx+1].value) { 
       ++cidx; 
      } 
     } 
     //swap if necessary                                                                                     
     if (heap[cidx].value < heap[idx].value) { 
      tmp = heap[cidx]; 
      heap[cidx] = heap[idx]; 
      heap[idx] = tmp; 
      idx = cidx; 
     } else { 
      break; 
     } 
    } 
} 

struct heapNode removeMin(struct heapNode* heap, int size) { 
    int cidx; 
    struct heapNode rv = heap[1]; 
    //printf("%d:%d:%dn", size, heap[1].value, heap[size].value);                                                                           
    heap[1] = heap[size]; 
    --size; 
    shiftdown(heap, size, 1); 
    return rv; 
} 

void enqueue(struct heapNode node, struct PQ *q) { 
    insert(node, q->heap, q->size); 
    ++q->size; 
} 

struct heapNode dequeue(struct PQ *q) { 
    struct heapNode rv = removeMin(q->heap, q->size); 
    --q->size; 
    return rv; 
} 

struct heapNode peak(struct PQ *q) { 
    return q->heap[1]; 
} 

void initQueue(struct PQ *q, int n) { 
    q->size = 0; 
    q->heap = (struct heapNode*)malloc(sizeof(struct heapNode)*(n+1)); 
} 

int nn = 1000000; 
struct PQ q; 

int main(int argc, char **argv) { 
    int n; 
    int i; 
    struct PQ q; 
    struct  heapNode hn; 
    n = atoi(argv[1]); 
    initQueue(&q, n); 
    srand(time(NULL)); 
    for (i = 0; i < n; ++i) { 
     hn.value = rand()%10000; 
     printf("enqueue node with value: %dn", hn.value); 
     enqueue(hn, &q); 
    } 
    printf("ndequeue all values:n"); 
    for (i = 0; i < n; ++i) { 
     hn = dequeue(&q); 
     printf("dequeued node with value: %d, queue size after removal: %dn", hn.value, q.size); 
    } 
} 

heap_inter.py

from cffi import FFI 

ffibuilder = FFI() 

ffibuilder.set_source("_heap_i", 
         r"""//passed to C compiler                                                                               
         #include <stdio.h>                                                                                 

         #include <stdlib.h>                                                                                 
         #include "cheap.h"                                                                                 
     """, 
           libraries=[]) 

ffibuilder.cdef("""                                                                                       
       struct heapData {                                                                                   
         char tx[64];                                                                                   
         int txID;                                                                                    
         char rx[64];                                                                                   
         int rxID;                                                                                    
         char name[64];                                                                                  
         float time;                                                                                   
         } ;                                                                                     

         struct heapNode {                                                                                  
         int value;                                                                                   
         struct heapData data;    //dummy                                                                           
         } ;                                                                                     

         struct PQ {                                                                                   
         struct heapNode* heap;                                                                                
         int size;                                                                                    
         } ;                                                                                     
""") 

#                                                                                           
# Rank (Simian Engine) has a Bin heap                                                                                  

if __name__ == "__main__": 
    ffibuilder.compile(verbose=True) 

その後、heap.py

from _heap_i import ffi, lib 

infTime = 0 

# /* create heap */                                                                    

def init(): 
    #global infTime                                                                    
    #infTime = int(engine.infTime) + 1                                                               
    cheap = ffi.new("struct PQ *") 
    lib.initQueue(cheap,nn) 
    return cheap 

def push(arr, element): 
    hn = ffi.new("struct heapNode") 
    value = element["time"] 
    hn.value = value 

    rx = ffi.new("char[]", element["rx"]) 
    hn.data.rx = rx 
    tx = ffi.new("char[]", element["tx"]) 
    hn.data.tx = tx 
    txID = ffi.new("int", element["txID"]) 
    hn.data.txID = txID 
    rxID = ffi.new("int", element["rxID"]) 
    hn.data.rxID = rxID 
    name = ffi.new("int", element["name"]) 
    hn.data.name = name 

    hn.data.time = value 

    result = lib.enqueue(hn, arr) 

def pop(arr): 
    hn = lib.dequeue(arr) 
    element = {"time": hn.value, 
       "rx" : hn.data.rx, 
       "tx" : hn.data.tx, 
       "rxID" : hn.data.rxID, 
       "txID" : hn.data.txID, 
       "name" : hn.data.name, 
       "data" : hn.data.data, 
       } 
    return element 

def annihilate(arr, event): 
    pass 

def peak(arr): 
    hn = lib.peak(arr) 
    element = {"time": hn.value, 
       "rx" : hn.data.rx, 
       "tx" : hn.data.tx, 
       "rxID" : hn.data.rxID, 
       "txID" : hn.data.txID, 
       "name" : hn.data.name, 
       "data" : hn.data.data, 
       } 
    return element 


def isEvent(arr): 
    if arr.size: 
     return 1 
    else: 
     return None 

def size(arr): 
    return arr.size 

し、最終的に見ているためtest_heap.py

import heap 

pq = heap.init() 

for x in range(1000) : 
    heap.push({"time" : x, 
       "rx" : "a", 
       "tx" : "b", 
       "txID" : 1, 
       "rxID" : 1, 
       "name" : "bob", 
       "data": "none", 
       },pq) 

for x in range(100) : 
    heap.peak(pq) 

for x in range(1000): 
    y = heap.dequeue(pq) 
    print y 

おかげで誰も、あなたが前にこれを経験しているなら、私に知らせてください。

答えて

2

heap.cについては、ffi.set_source()に通知する必要があります。最も簡単な方法は、this exampleのよう

with open('heap.c', 'r') as fid: ffi.set_source(fid.read())

です。それが動作する方法は次のとおりです。これらの機能を実装するソースコードが指定されている

  • 関数の宣言、構造体、列挙型、のpythonからアクセスできるようになりますtypedefでは、あなたのffi.cdefに表示されます(...)
  • ffi.set_source(...)への文字列としても使用できます(distutilsのキーワードもあります)。
  • ffi.compile()は、ffi.cdef()で定義されたものをエクスポートし、ものはPythonに公開されます
+0

これは非常に役に立ちました。私はドキュメントが混乱していると思います。 push関数は 'hn'を置き換える' element'を持つ最後の行にすぎません。 – channon

0

ffi.cdef()に関数宣言がないため、結果の_heap_iライブラリは関数をエクスポートしません。 .hファイルから関数宣言をコピーして貼り付けてください。

+0

hmmm ...次にこのエラーが発生します 'NC $ pypy test_heap.py トレースバック(最新の呼び出しの最後):_heap_i輸入FFIから 輸入ヒープ heap.py」、6行目で ファイル "test_heap.py"、ライン1、、、 lib ImportError:拡張モジュール '_heap_i.pypy-41.so'を読み込めません:dlopen(_heap_i.pypy-41.so、6):シンボルが見つかりません:_initQueue 参照先:_heap_i.pypy-41.so 予想されるin:flat namespace in _heap_i.pypy-41.so nc $ ' – channon

関連する問題