2013-06-14 53 views
6

Vì vậy, tôi đang sử dụng python để gọi các phương thức trong một thư viện C++ dùng chung. Tôi đang gặp một vấn đề chuyển đổi một mảng 2D numpy thành một mảng C++ 2D của quần short như là một đầu vào chức năng. Tôi đã tạo ra một ví dụ đồ chơi thể hiện vấn đề. Vui lòng biên dịch và dùng thử!Chuyển đổi một mảng numpy 2D thành C++ ngắn **?

Đây là mã python (soexample.py):

# 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) 

Đây là Thư viện C++ (soexample.cpp):

#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);  
    } 
} 

mà tôi biên soạn với lệnh sau đây:

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

Khi tôi chạy tệp python, tôi nhận được lỗi sau:

>> 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 

Làm cách nào để sửa lỗi này không may TypeError?

+1

Tôi tin ints ngắn C là 16 bit. Mặt khác, int mặc định thường là 32 bit. Bạn có thể thử tạo mảng của mình dưới dạng 'array = np.array ([[1,2,3], [1,2,3]], dtype = np.uint16)' và xem điều gì xảy ra. – Jaime

Trả lời

4

Bạn có thể sử dụng ctypes 's c_shortPOINTER để trợ giúp chuyển đổi trung gian. Hàm sau biến một mảng thành một mảng 2-bit kiểu C có thể được truyền vào một hàm C mong đợi một 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 

Note, tôi sửa đổi func_pyCPPClass::func để mất 2 tham số bổ sung, chiều rộng và chiều dài của mảng nhất định. Với điều này, CPPClass::func có thể in ra tất cả các yếu tố của mảng:

// ... 
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); 
} 

Với chức năng helper được xác định, sau đây bây giờ sẽ làm việc:

>>> 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

Cảm ơn! Điều đó làm việc hoàn hảo. Tôi có một câu hỏi tương tự khác mà bạn có thể giúp tôi ở đây: http://stackoverflow.com/questions/17138054/return-c-double-to-python – dillerj

Các vấn đề liên quan