2012-01-23 40 views
5

Tôi đang gặp sự cố khi sử dụng các hàm từ thư viện được chia sẻ được xuất với giao diện SWIG .dll.Sử dụng các chức năng bọc SWIG từ Windows .dll

Version Info

Python: 2.6.4

Swig: 2.0.4

Bức tranh lớn là: Tôi có một số mã được phát triển trong Linux bằng C++ và được bọc bằng SWIG. Tôi đã biên dịch nguồn C++ thành đối tượng .so trong Linux và sử dụng thư viện .so bằng Python.

Bây giờ, tôi cần di chuyển tất cả các chức năng này sang cửa sổ và tương đương với .so trong Windows là .dll. Vì vậy, tôi đã lên kế hoạch biên dịch tất cả các mã nguồn C++ thành một .dll và truy cập chúng thông qua Python.

Vì vậy, thủ tục bình thường sẽ là: có nguồn C++ -> bọc chúng bằng SWIG -> biên dịch thành .dll -> truy cập thông qua Python.

Có một tệp nguồn lớn .cxx được tạo bằng SWIG chứa tất cả các chức năng tôi đã phát triển. Nhiệm vụ bây giờ là biên dịch tập tin được tạo ra SWIG này thành một .dll để tôi có thể sử dụng tất cả các chức năng sau này. Tuy nhiên, tệp .cxx sử dụng một số cách kỳ lạ để gói tất cả các chức năng của tôi và tôi không có đầu mối làm thế nào để sử dụng chúng.

Các chức năng được bao bọc như sau. Ssay Tôi có một ++ lớp C gọi sdrts_reverse_burst_ff, sau khi gói, lớp trở thành một chức năng trong file .cxx và được định nghĩa như thế này:

SWIGINTERN PyObject *_wrap_sdrts_reverse_burst_ff_sptr___deref__(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { 

PyObject *resultobj = 0; 

boost::shared_ptr<sdrts_reverse_burst_ff> *arg1 = (boost::shared_ptr<sdrts_reverse_burst_ff> *) 0 ; 

    void *argp1 = 0 ; 

    int res1 = 0 ; 

    PyObject * obj0 = 0 ; 

    sdrts_reverse_burst_ff *result = 0 ; 



    if(!PyArg_UnpackTuple(args,(char *)"sdrts_reverse_burst_ff_sptr___deref__",1,1,&obj0)) SWIG_fail; 

    res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_boost__shared_ptrT_sdrts_reverse_burst_ff_t, 0 | 0); 

    if (!SWIG_IsOK(res1)) { 

    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "sdrts_reverse_burst_ff_sptr___deref__" "', argument " "1"" of type '" "boost::shared_ptr<sdrts_reverse_burst_ff> *""'"); 

    } 

    arg1 = reinterpret_cast< boost::shared_ptr<sdrts_reverse_burst_ff> * >(argp1); 

    result = (sdrts_reverse_burst_ff *)(arg1)->operator ->(); 

    resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_sdrts_reverse_burst_ff, 0 | 0); 

    return resultobj; 

fail: 

    return NULL; 

} 

Đó không phải là tất cả: gần cuối .cxx tập tin này có một mảng lớn trong đó có tất cả các chức năng lớp như thế này:

PyMethodDef SwigMethods[] = { 

    { (char *)"sdrts_reverse_burst_ff_sptr___deref__", _wrap_sdrts_reverse_burst_ff_sptr___deref__, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr___deref__(sdrts_reverse_burst_ff_sptr self)"}, 

    { (char *)"delete_sdrts_reverse_burst_ff_sptr", _wrap_delete_sdrts_reverse_burst_ff_sptr, METH_VARARGS, (char *)"delete_sdrts_reverse_burst_ff_sptr(sdrts_reverse_burst_ff_sptr self)"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_set_reverse_burst", _wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_set_reverse_burst(sdrts_reverse_burst_ff_sptr self, int samples) -> int"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_enable_reverse_burst", _wrap_sdrts_reverse_burst_ff_sptr_enable_reverse_burst, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_enable_reverse_burst(sdrts_reverse_burst_ff_sptr self) -> int"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_reset", _wrap_sdrts_reverse_burst_ff_sptr_reset, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_reset(sdrts_reverse_burst_ff_sptr self) -> int"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_history", _wrap_sdrts_reverse_burst_ff_sptr_history, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_history(sdrts_reverse_burst_ff_sptr self) -> unsigned int"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_output_multiple", _wrap_sdrts_reverse_burst_ff_sptr_output_multiple, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_output_multiple(sdrts_reverse_burst_ff_sptr self) -> int"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_relative_rate", _wrap_sdrts_reverse_burst_ff_sptr_relative_rate, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_relative_rate(sdrts_reverse_burst_ff_sptr self) -> double"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_start", _wrap_sdrts_reverse_burst_ff_sptr_start, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_start(sdrts_reverse_burst_ff_sptr self) -> bool"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_stop", _wrap_sdrts_reverse_burst_ff_sptr_stop, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_stop(sdrts_reverse_burst_ff_sptr self) -> bool"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_nitems_read", _wrap_sdrts_reverse_burst_ff_sptr_nitems_read, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_nitems_read(sdrts_reverse_burst_ff_sptr self, unsigned int which_input) -> uint64_t"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_nitems_written", _wrap_sdrts_reverse_burst_ff_sptr_nitems_written, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_nitems_written(sdrts_reverse_burst_ff_sptr self, unsigned int which_output) -> uint64_t"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_detail", _wrap_sdrts_reverse_burst_ff_sptr_detail, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_detail(sdrts_reverse_burst_ff_sptr self) -> gr_block_detail_sptr"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_set_detail", _wrap_sdrts_reverse_burst_ff_sptr_set_detail, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_set_detail(sdrts_reverse_burst_ff_sptr self, gr_block_detail_sptr detail)"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_name", _wrap_sdrts_reverse_burst_ff_sptr_name, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_name(sdrts_reverse_burst_ff_sptr self) -> string"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_input_signature", _wrap_sdrts_reverse_burst_ff_sptr_input_signature, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_input_signature(sdrts_reverse_burst_ff_sptr self) -> gr_io_signature_sptr"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_output_signature", _wrap_sdrts_reverse_burst_ff_sptr_output_signature, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_output_signature(sdrts_reverse_burst_ff_sptr self) -> gr_io_signature_sptr"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_unique_id", _wrap_sdrts_reverse_burst_ff_sptr_unique_id, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_unique_id(sdrts_reverse_burst_ff_sptr self) -> long"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_to_basic_block", _wrap_sdrts_reverse_burst_ff_sptr_to_basic_block, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_to_basic_block(sdrts_reverse_burst_ff_sptr self) -> gr_basic_block_sptr"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_check_topology", _wrap_sdrts_reverse_burst_ff_sptr_check_topology, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_check_topology(sdrts_reverse_burst_ff_sptr self, int ninputs, int noutputs) -> bool"}, 

    { (char *)"sdrts_reverse_burst_ff_sptr_swigregister", sdrts_reverse_burst_ff_sptr_swigregister, METH_VARARGS, NULL}, 

    { (char *)"reverse_burst_ff", _wrap_reverse_burst_ff, METH_VARARGS, (char *)"reverse_burst_ff(int max_samples) -> sdrts_reverse_burst_ff_sptr"}, 

    { NULL, NULL, 0, NULL } 

}; 

tôi đi theo kinh nghiệm cũ của tôi với .dll s và xuất khẩu tất cả các chức năng với một __declspec(dllexport) đầu đơn giản. Trong Python, tôi cũng có thể gọi số _wrap_sdrts_reverse_burst_ff_sptr___deref__ Tôi đã xuất:

import ctypes 

_dll_func_list = ctypes.WinDLL("func.dll") 

_reverse_burst_ref = _dll_func_list._wrap_sdrts_reverse_burst_ff_sptr___deref__ 

Tuy nhiên, đó là điều xa nhất tôi có thể tiếp cận. Khi tôi cố gắng truy cập vào các chức năng phụ trong lớp đó, ví dụ,

_class_ref._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0) 

máy chết tiệt nói với tôi:

'_wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst' cannot be found.

Khi tôi cố gắng gọi hàm trực tiếp và vượt qua trong một tham số như thế này :

_dll_func_list ._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0) 

Chiếc máy nói

WindowsError: exception: access violation reading 0x00000004

Có ai biết cách truy cập các chức năng được bọc SWIG đã xuất bằng Python không?

Trả lời

2

SWIG cũng tạo tệp .py, ngoài tệp .cxx.Một khi bạn đã xây dựng một DLL (hoặc chia sẻ đối tượng) trên nền tảng của bạn tất cả các bạn cần phải làm gì để sử dụng bằng Python chính nó là

import ModuleName 

nơi ModuleName là những gì bạn nói với SWIG để gọi các mô-đun, hoặc thông qua %module trong tệp .i cho từ dòng lệnh khi bạn gọi nó.

Trong SWIG được tạo ra Python có mã để xử lý tải DLL cho bạn - không cần phải sử dụng ctypes hoặc bất cứ điều gì như thế với nó. Mã được tạo ra khớp với giao diện mà bạn đã yêu cầu SWIG để bọc chặt chẽ nhất có thể trong Python và kỳ diệu đưa các cuộc gọi đến bên C++ cho bạn.

Vì vậy, nếu sdrts_reverse_burst_ff là một chức năng miễn phí mà bạn có thể làm:

import ModuleName 

ModuleName.sdrts_reverse_burst_ff() 

Bạn cần phải chắc chắn rằng bạn xây dựng các DLL với tên SWIG hy vọng nó có - nó sẽ được khá rõ ràng từ các ngoại lệ mà Python tăng nếu đó không phải là trường hợp. Bạn có thể cũng muốn liên kết nó với việc triển khai của bạn có chứa sdrts_reverse_burst_ff() trừ khi đó là chức năng chỉ có tiêu đề.

+0

Tôi sử dụng tệp python được tạo và nó có trình trợ giúp nhập. Nhưng nó không thành công khi import _my_dll, và nó nói: ImportError: Không có module _my_dll. Tôi đã thêm đường dẫn tuyệt đối vào _my_dll vào cả PYTHONPATH và LD_LIBRARY_PATH, nó sẽ có thể tìm thấy nó. – user1165959

+0

@ user1165959 - bạn cần phải chắc chắn rằng nó được gọi là * chính xác * "_my_dll.dll" sau đó nếu đó là những gì Python than phiền về. Trên các hệ thống Windows, tôi có xu hướng chỉ đặt nó vào thư mục hiện tại tại điểm mà Python được gọi. Dù bằng cách nào ctypes không phải là cách để sửa chữa nó - bạn cần phải sửa chữa đường dẫn + tải vấn đề và nó sẽ tất cả chỉ hoạt động trở lại. – Flexo

+1

Có, nó được gọi là _my_dll.dll chính xác, và tôi cũng đã thử đặt nó dưới c: \ Python27 và nó vẫn không thể tìm thấy nó. Nó chỉ có thể tìm thấy dll khi sử dụng ctypes.WinDLL ("_ my_dll.dll"). Nhưng kể từ khi bạn đề cập nó không phải là cách để làm điều đó, tôi có một cảm giác rằng dll này tôi thực hiện đã không được biên dịch sang một định dạng dễ nhận biết để SWIG. Cách tôi sử dụng swig là: swig -module _my_dll -fvirtual -python -modern -C++ -outdir. -o _my_dll.cxx _my_dll.i và sau đó tôi biên dịch _my_dll.cxx thành một dll cùng với src tôi đã sử dụng để tạo ra _my_dll.i bằng cách sử dụng VC++ 2008 express edition. Bất cứ điều gì tôi đã làm sai? – user1165959

1

Vì vậy, câu trả lời ngắn cuối cùng có vẻ là bản dựng C++ sẽ sản xuất _my_dll.pyd (không phải _my_dll.dll) để có thể nhập my_dll bằng Python trên Windows. Điều này trái ngược với bản xây dựng Linux, nơi người ta sẽ xây dựng _my_dll.so

Chỉ cần đổi tên tệp .dll thành tệp .pyd, nhưng tốt hơn là xây dựng nó, như được nêu trong các nhận xét ở trên.

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