Bên cạnh Boost.Python (có lẽ là giải pháp thân thiện hơn cho các dự án lớn hơn yêu cầu ánh xạ một-một của các lớp C++ tới các lớp python), bạn có thể cung cấp giao diện C bên C++. Đó là một trong những giải pháp của nhiều người vì vậy nó có sự đánh đổi thương mại riêng của mình, nhưng tôi sẽ trình bày nó vì lợi ích của những người không quen thuộc với kỹ thuật này. Để tiết lộ đầy đủ, với cách tiếp cận này, người ta sẽ không giao tiếp C++ với python, nhưng C++ thành C tới Python. Dưới đây tôi bao gồm một ví dụ đáp ứng yêu cầu của bạn để cho bạn thấy ý tưởng chung về cơ sở "c" bên ngoài của trình biên dịch C++.
//YourFile.cpp (compiled into a .dll or .so file)
#include <new> //For std::nothrow
//Either include a header defining your class, or define it here.
extern "C" //Tells the compile to use C-linkage for the next scope.
{
//Note: The interface this linkage region needs to use C only.
void * CreateInstanceOfClass(void)
{
// Note: Inside the function body, I can use C++.
return new(std::nothrow) MyClass;
}
//Thanks Chris.
void DeleteInstanceOfClass (void *ptr)
{
delete(std::nothrow) ptr;
}
int CallMemberTest(void *ptr)
{
// Note: A downside here is the lack of type safety.
// You could always internally(in the C++ library) save a reference to all
// pointers created of type MyClass and verify it is an element in that
//structure.
//
// Per comments with Andre, we should avoid throwing exceptions.
try
{
MyClass * ref = reinterpret_cast<MyClass *>(ptr);
return ref->Test();
}
catch(...)
{
return -1; //assuming -1 is an error condition.
}
}
} //End C linkage scope.
Bạn có thể biên dịch mã này với
gcc -shared -o test.so test.cpp
#creates test.so in your current working directory.
Trong mã python của bạn, bạn có thể làm một cái gì đó như thế này (nhắc tương tác từ 2.7 hiển thị):
>>> from ctypes import cdll
>>> stdc=cdll.LoadLibrary("libc.so.6") # or similar to load c library
>>> stdcpp=cdll.LoadLibrary("libstdc++.so.6") # or similar to load c++ library
>>> myLib=cdll.LoadLibrary("/path/to/test.so")
>>> spam = myLib.CreateInstanceOfClass()
>>> spam
[outputs the pointer address of the element]
>>> value=CallMemberTest(spam)
[does whatever Test does to the spam reference of the object]
Tôi chắc chắn Boost .Python làm một cái gì đó tương tự dưới mui xe, nhưng có lẽ sự hiểu biết các khái niệm cấp thấp hơn là hữu ích. Tôi sẽ vui mừng hơn về phương pháp này nếu bạn đang cố truy cập chức năng của thư viện C++ và không cần phải có ánh xạ một-một.
Để biết thêm thông tin về C/C++ tương tác kiểm tra trang này từ Sun: http://dsc.sun.com/solaris/articles/mixing.html#cpp_from_c
Thật vậy, đây là một chút tẻ nhạt, nhưng nó hoạt động. Bạn sẽ đặc biệt muốn xem ra cho ngoại lệ mặc dù. Tôi không nghĩ rằng nó an toàn để giả định các mô-đun 'ctypes' xử lý các chức năng C mà ném ngoại lệ rất tốt. Cụ thể, câu lệnh 'return new MyClass;' rất nguy hiểm vì nó có thể tăng 'std :: bad_alloc'. –
Vui lòng thêm chức năng 'DestroyInstanceOfClass()'. –
Đó là một điểm rất tốt. Tôi sẽ chỉnh sửa ví dụ để sử dụng không có biến thể ném. Một mẹo khác là bắt tất cả các ngoại lệ trong khối thử trong cơ thể C++ của hàm. – AudaAero