2013-06-14 7 views
6

तो मैं साझा सी ++ लाइब्रेरी में कॉल विधियों को कॉल करने के लिए पायथन का उपयोग कर रहा हूं। मुझे एक फंक्शन इनपुट के रूप में शॉर्ट्स के सी ++ 2 डी सरणी में एक numpy 2D सरणी को परिवर्तित करने में कोई समस्या है। मैंने एक खिलौना उदाहरण बनाया है जो समस्या को प्रदर्शित करता है। संकलित करने के लिए स्वतंत्र महसूस करें और इसे आजमाएं!एक 2 डी numpy सरणी C++ लघु ** में कनवर्ट करें?

#include <iostream> 

using namespace std; 

class CPPClass 
{ 
    public: 
    CPPClass(){} 

    void func(unsigned short **array) 
    { 
     cout << array[0][0] << endl; 
    } 
}; 

// For use with python: 
extern "C" { 
    CPPClass* CPPClass_py(){ return new CPPClass(); } 
    void func_py(CPPClass* myClass, unsigned short **array) 
    {  
     myClass->func(array);  
    } 
} 

जो मैं निम्न आदेश के साथ संकलन:

# Python imports 
from ctypes import CDLL 
import numpy as np 

# Open shared CPP library: 
cpplib=CDLL('./libsoexample.so') 
cppobj = cpplib.CPPClass_py() 

# Stuck on converting to short**? 
array = np.array([[1,2,3],[1,2,3]]) 
cpplib.func_py(cppobj,array) 

यहाँ सी ++ पुस्तकालय (soexample.cpp) है:

यहाँ अजगर कोड (soexample.py) है

g++ -fPIC -Wall -Wextra -shared -o libsoexample.so soexample.cpp 

जब मैं पाइथन फ़ाइल चलाता हूं, तो मुझे निम्न त्रुटि मिलती है:

>> python soexample.py 
Traceback (most recent call last): 
    File "soexample.py", line 13, in <module> 
    cpplib.func_py(cppobj,array) 
ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: Don't know how to  convert parameter 2 

मैं इस दुर्भाग्यपूर्ण TypeError को सही तरीके से कैसे ठीक करूं?

+1

मेरा मानना ​​है कि सी की लघु ints 16 बिट कर रहे हैं। दूसरी तरफ डिफ़ॉल्ट numpy int आमतौर पर 32 बिट्स है। आप अपनी सरणी को 'array = np.array ([[1,2,3], [1,2,3]], dtype = np.uint16) के रूप में बनाने का प्रयास कर सकते हैं और देखें कि क्या होता है। – Jaime

उत्तर

4

इंटरमीडिएट रूपांतरण में सहायता के लिए आप ctypes के c_short और POINTER का उपयोग कर सकते हैं। निम्न फ़ंक्शन एक numpy सरणी को एक सी-प्रकार 2darray में बदल देता है जिसे short ** की अपेक्षा रखने वाले सी फ़ंक्शन में पारित किया जा सकता है।

def c_short_2darr(numpy_arr): 
    c_short_p = POINTER(c_short) 
    arr = (c_short_p * len(numpy_arr))() 
    for i in range(len(numpy_arr)): 
    arr[i] = (c_short * len(numpy_arr[i]))() 
    for j in range(len(numpy_arr[i])): 
     arr[i][j] = numpy_arr[i][j] 
    return arr 

ध्यान दें, मैं func_py और CPPClass::func संशोधित 2 अतिरिक्त पैरामीटर, चौड़ाई और दिए गए सरणी की लंबाई लेने के लिए। इस के साथ, CPPClass::func सरणी के तत्वों के सभी प्रिंट कर सकते हैं:

// ... 
void CPPClass::func(unsigned short **array, size_t w, size_t h) 
{ 
    for(size_t i = 0; i < w; ++i) 
    { 
     for(size_t j = 0; j < h; ++j) 
      cout << array[i][j] << ", "; 
     cout << '\n'; 
    } 
} 
// ... 
void func_py(CPPClass *myClass, 
      unsigned short **array, 
      size_t w, size_t h) 
{ 
    myClass->func(array, w, h); 
} 
कि सहायक समारोह परिभाषित के साथ

, निम्नलिखित अब काम करना चाहिए:

>>> arr = numpy.array([ [1,2,3], [4,5,6] ]) 
>>> arr 
array([[1, 2, 3], 
     [4, 5, 6]]) 
>>> cpplib.func_py(cppobj, c_short_2darr(arr), 2, 3) 
1, 2, 3, 
4, 5, 6, 
0 
+0

धन्यवाद! यह पूरी तरह से काम किया। मेरे पास एक और समान सवाल है कि आप यहां मेरी सहायता कर सकते हैं: http://stackoverflow.com/questions/17138054/return-c-double-to-python – dillerj

संबंधित मुद्दे