2010-12-29 42 views
16

Tôi có thể đặt một lớp bên trong một DLL không? Lớp tôi đã viết là:Làm thế nào để sử dụng một lớp trong DLL?

class SDLConsole 
{ 
     public: 
      SDLConsole(); 
      ~SDLConsole(){}; 
      void getInfo(int,int); 
      void initConsole(char*, char*, SDL_Surface*, int, int, int); 
      void sendMsg(char*,int, SDL_Surface*); 
      void cls(SDL_Surface*); 

     private: 
       TTF_Font *font; 
       SDL_Surface *consoleImg; 
       int width, pos, height, line, size, ctLine; 
       SDL_Surface* render(char*,int); 

}; 

tôi biết làm thế nào để tải một DLL và sử dụng các chức năng bên trong một DLL, nhưng làm thế nào tôi có thể đặt một lớp bên trong một DLL? Cảm ơn nhiều.

+0

Tôi tin rằng mọi thứ bạn cần là [ở đây] (http://msdn.microsoft.com/en-us/library/a90k134d.aspx) – icecrime

+0

Bạn đã thử chưa? – BlackBear

Trả lời

20

Nếu bạn sử dụng liên kết động thời gian chạy (sử dụng LoadLibrary để tải dll), bạn không thể truy cập trực tiếp lớp, bạn cần khai báo giao diện cho lớp của bạn và tạo hàm trả về một thể hiện của lớp này, như sau:

class ISDLConsole 
{ 
    public:    
     virtual void getInfo(int,int) = 0; 
     virtual void initConsole(char*, char*, SDL_Surface*, int, int, int) = 0; 
     virtual void sendMsg(char*,int, SDL_Surface*) = 0; 
     virtual void cls(SDL_Surface*) = 0; 
}; 

class SDLConsole: public ISDLConsole 
{ 
    //rest of the code 
}; 

__declspec(dllexport) ISDLConsole *Create() 
{ 
    return new SDLConsole(); 
} 

Ngược lại, nếu bạn liên kết các dll trong thời gian tải, chỉ cần sử dụng các thông tin được cung cấp bởi icecrime: http://msdn.microsoft.com/en-us/library/a90k134d.aspx

+0

Cách này mạnh hơn '__declspec (dllexport)'. Ngay cả liên kết tải thời gian cũng nên sử dụng phương pháp này. –

+0

@Ben: tại sao nó mạnh mẽ hơn? –

+5

Vì chỉ có bố cục bảng v phải khớp giữa thư viện và ứng dụng khách, tương đối dễ thực hiện, ngay cả giữa các ngôn ngữ khác nhau.Mặt khác, với '__declspec (dllexport)' mọi thứ phải khớp với: nhà cung cấp trình biên dịch, phiên bản trình biên dịch, tùy chọn biên dịch, hoặc bạn sẽ kết thúc với sự không phù hợp mang tên (lỗi liên kết) hoặc vi phạm quy tắc một định nghĩa và các sự cố tương ứng. –

4

bạn có thể, và tất cả các thông tin mà bạn cần là trên this pagethis page:

#ifdef _EXPORTING 
    #define CLASS_DECLSPEC __declspec(dllexport) 
#else 
    #define CLASS_DECLSPEC __declspec(dllimport) 
#endif 

class CLASS_DECLSPEC SDLConsole 
{ 
    /* ... */ 
}; 

Tất cả những gì còn lại là xác định ký hiệu tiền xử lý _EXPORTING khi tạo DLL.

+2

Đó không phải là "tất cả những gì còn lại". Bạn cũng cần đảm bảo rằng trình biên dịch chính xác được sử dụng để xây dựng DLL và tất cả các máy khách, các tùy chọn trình biên dịch cũng phù hợp. Bạn phải trả một hình phạt bảo trì rất lớn để làm những việc theo cách này, [giao diện ảo thuần túy theo đề xuất của bcsanches] (http://stackoverflow.com/questions/4555961/how-to-use-a-class-in-dll/4556025 # 4556025) là tốt hơn nhiều. –

+0

@Ben: bạn có thể đúng, nhưng tôi phải thừa nhận tôi đã luôn luôn làm mọi thứ theo cách này và tôi không thể tưởng tượng bằng cách sử dụng phương pháp 'giao diện ảo thuần túy' trên một dự án lớn – icecrime

+0

Nếu bạn có các mô-đun kết hợp chặt chẽ bởi vì tất cả chúng đều là cục bộ cho một dự án duy nhất, tại sao không chỉ sử dụng các thư viện tĩnh? –

12

Solution đề xuất bởi bcsanches,

__declspec(dllexport) ISDLConsole *Create() 
{ 
    return new SDLConsole(); 
} 

Nếu bạn đang đi để sử dụng phương pháp này như suggested bởi bcsanches, sau đó hãy chắc chắn rằng bạn sử dụng chức năng sau đây để delete đối tượng của bạn,

__declspec(dllexport) void Destroy(ISDLConsole *instance) 
{ 
     delete instance; 
} 

Xác định các chức năng như vậy luôn là trong cặp, vì nó đảm bảo mà bạn xóa các đối tượng của mình khỏi cùng một vùng nhớ/vùng nhớ/etc mà chúng đã được tạo trên đó. Xem này pair-functions

+0

Tôi muốn tạo một dll ra khỏi lớp C++ của tôi và sử dụng dll đó trong ứng dụng C# của tôi. bạn có thể hướng dẫn tôi về điều đó không? những gì khác là cần thiết? làm thế nào tôi có thể gọi dll của tôi trong C# khi tôi tạo ra nó theo cách này? – Breeze

+1

@Hossein: Tìm kiếm pinvoke trong C#. Bạn sẽ tìm thấy rất nhiều chủ đề trên đó. – Nawaz

+0

bạn có nghĩa là tôi cần phải sử dụng DIIIMport thông thường giống như dlls bình thường (chẳng hạn như user32.dll)? ok, tôi sẽ thử nó – Breeze

2

Nếu bạn muốn hiển thị dữ liệu trong một lớp, các giải pháp trên sẽ không cắt nó. Bạn phải tát một số __declspec(dllexport) vào chính lớp đó trong bản dịch DLL và __declspec(dllimport) trong mô-đun liên kết đến tệp DLL.

Một kỹ thuật phổ biến là để làm điều này (Microsoft trình thuật sĩ tạo ra mã như thế này):

#ifdef EXPORT_API 
#define MY_API __declspec(dllexport) 
#else 
#define MY_API __declspec(dllimport) 
#endif 

class MY_API MyClass { 
    ... 
}; 

Sau đó, hãy chắc chắn EXPORT_API được định nghĩa trong dự án DLL, và chắc chắn rằng nó không được định nghĩa trong module liên kết đến DLL.

Nếu bạn tạo dự án DLL mới trong Visual C++ từ đầu và chọn hộp kiểm "Xuất ký hiệu", một số mã mẫu sẽ được tạo bằng kỹ thuật này.

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