2011-01-21 43 views
5

Tôi đang lên kế hoạch thực hiện giao diện plugin C++ ala How to create some class from dll(constructor in dll)?(с++) nhưng giao diện được sử dụng để tạo DLL qua MinGW hoặc Borland và trình tải DLL được biên dịch bằng MSVC++, có thể có các vấn đề. Kể từ khi chức năng xuất khẩu duy nhất được khai báo bên ngoài "C" Tôi không thấy lý do tại sao nó sẽ không hoạt động?C++ Giao diện plugin DLL

Ý tưởng?

Trả lời

10

Nếu bạn muốn tương thích giữa các trình biên dịch (và Release/Debug) và sử dụng C++, bạn cần nỗ lực nhiều hơn một chút.

Về cơ bản - bạn được phép chuyển các kiểu dữ liệu cơ bản và trỏ đến các lớp ảo thuần túy. Các lớp này không được chứa bất kỳ thành viên dữ liệu nào, hàm hủy của chúng không được công khai và chúng không có các hàm quá tải.

Bộ nhớ không được cấp phát trong một dll và được phát hành trong một dll khác. Điều này có nghĩa là không có ngoại lệ và bạn cần một số loại tính toán tham chiếu hoặc trả về.

Tất cả các phương thức bên trong lớp ảo thuần túy (còn gọi là "Giao diện") phải được đánh dấu bằng quy ước cuộc gọi (tôi thích stdcall).

Cụm động cũng không thể thực hiện được, vì vậy bạn có thể cần một số chức năng trong tất cả các giao diện của bạn để thực hiện thủ thuật (như QueryInterface trong COM).

Điều này làm việc vì hầu hết trình biên dịch trên win32 cố gắng tương thích COM và giải quyết các vấn đề tương tự theo cách tương thích COM. Để có giao diện đầu tiên, bạn cần một hàm C đơn giản được xuất từ ​​dll.

Nếu bạn chỉ sử dụng các hàm C và C, mọi thứ sẽ hoạt động. Nhưng sau đó bạn được giới hạn trong C mà không có lớp thừa kế &.

Tôi hy vọng rằng sẽ giúp.


Tên mangling không phải là một vấn đề:

1: nếu bạn sử dụng chức năng C với các loại C dữ liệu, tất cả mọi thứ được định nghĩa, không có tên mangling (ngoại lệ: trong VS với stdcall, bạn cần phải remap tên cho tên C "bình thường" thông qua chỉ thị của Linker)

Thứ hai: Phương thức bên trong các lớp học không được xuất và do đó không bị xáo trộn. Bạn gọi các phương thức thông qua con trỏ tới các lớp ảo thuần túy (còn gọi là "Giao diện"). Điều này sử dụng một offset và không có tên. Bạn vẫn không thể sử dụng destructor, vì vị trí của destructor bên trong vtbl không cố định theo như tôi biết.


Nếu bạn chuyển cấu trúc cho các chức năng/phương pháp, hãy đảm bảo sửa căn chỉnh. Nó không được định nghĩa trên các trình biên dịch khác nhau.

+0

Còn tên mangling thì sao? Nó sẽ là như nhau cho các destructor trong trình biên dịch khác nhau? – ssmir

+0

Vì vậy, điều đó có nghĩa là bạn không thể sử dụng một plugin được tạo bằng trình biên dịch khác vì biểu tượng cho vtable có thể khác nhau và thậm chí là bù đắp phương thức có thể khác nhau? – ssmir

+0

Nhưng không phải là cấu trúc vtable được xác định bởi tiêu chuẩn C++? Sau đó, nó không phải là vấn đề để sử dụng một trình biên dịch (tuân thủ) khác nhau. – Robert

0

Ý tưởng có thể đang sử dụng hàm extern C chuẩn để tạo ClassFactory. Có một số convenction về một cố định (hoặc nhiều hơn) điểm vào dll phải tiếp xúc là một plugin hợp lệ.

+0

Có, chức năng duy nhất được xuất sẽ là một "C" Plugin bên ngoài * GetPluginObject(). Tôi đã làm điều này trước đây, nhưng sau đó tôi đã kiểm soát các DLL (tức là không cho phép MinGW/Borland, vv vào phương trình) – Robert

+0

Điều gì xảy ra nếu GetPluginObject của bạn trả về một số lớp bắt nguồn từ một số lớp * pure * virtual, aren Không thể tương thích VTable giữa việc thực hiện trình biên dịch khác nhau? Tôi nghĩ rằng MS COM tận dụng những ý tưởng này ... –

+0

chúng được, để mở rộng một số. Xem câu trả lời của tôi ở trên. –