2010-12-29 5 views
16

Можно ли разместить класс внутри DLL? класса я написал это:Как использовать класс в 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); 

}; 

Я знаю, как загрузить DLL и использовать функцию внутри DLL, но как я могу поставить класс внутри DLL? Большое спасибо.

+0

Я считаю, что все, что вам нужно [здесь] (http://msdn.microsoft.com/en-us/library/a90k134d.aspx) – icecrime

+0

Вы пробовали? – BlackBear

ответ

20

Если вы используете динамическую компоновку времени выполнения (использует LoadLibrary для загрузки DLL), вы не можете получить доступ к классу напрямую, вам нужно объявить интерфейс для своего класса и создать функцию, которая возвращает экземпляр этого класса, например:

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

в противном случае, если вы связываете DLL во время загрузки, просто использовать информацию, предоставленную icecrime: http://msdn.microsoft.com/en-us/library/a90k134d.aspx

+0

Этот способ гораздо более надежный, чем '__declspec (dllexport)'. Этот метод должен использовать даже привязка времени загрузки. –

+0

@Ben: почему он более надежный? –

+5

Потому что только макет v-таблицы должен соответствовать библиотеке и клиенту, что относительно легко выполнить, даже между разными языками.С другой стороны, с '__declspec (dllexport)' все должно соответствовать: поставщику компилятора, версии компилятора, параметрам компиляции, или вы либо закончите несоответствие имен (ошибка ссылки), либо нарушение правил с одним определением и соответствующие аварии. –

4

вы можете, и всю необходимую информацию находятся на this page и this page:

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

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

Все, что осталось, это определить символ препроцессора _EXPORTING при создании библиотеки DLL.

+2

Это не «все, что осталось». Вы также должны убедиться, что тот же самый точный компилятор используется для построения библиотеки DLL и всех клиентов, что также соответствует параметрам компилятора. Вы платите огромную штрафную санкционируемость за то, что вы делаете это, [чистый виртуальный интерфейс, предложенный bcsanches] (http://stackoverflow.com/questions/4555961/how-to-use-a-class-in-dll/4556025 # 4556025) намного лучше. –

+0

@Ben: вы, вероятно, правы, но я должен признать, что я всегда делал это так, и я просто не могу представить, как использовать метод «чистого виртуального интерфейса» для большого проекта. – icecrime

+0

Если у вас есть модули, которые тесно связаны друг с другом, потому что все они локальны для одного проекта, почему бы просто не использовать статические библиотеки? –

12

Solution предложил bcsanches,

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

Если вы собираетесь использовать этот подход как suggested по bcsanches, то убедитесь, что вы используете следующую функцию delete вашего объекта,

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

Определить такие функции всегда в pair, так как он обеспечивает, что вы удаляете свои объекты из того же кучи/пула памяти и т. д., на которых они были созданы. См. Это pair-functions

+0

Я хочу создать dll из моего класса C++ и использовать эту DLL в моем приложении C#. Можете ли вы, пожалуйста, направить меня на это тоже? что еще нужно? как я могу назвать свою dll в C#, когда создаю ее таким образом? – Breeze

+1

@ Хоссейн: поиск pinvoke в C#. На нем вы найдете множество тем. – Nawaz

+0

Вы имеете в виду, что мне нужно использовать обычный DIIIMport так же, как и обычные DLL (например, user32.dll)? хорошо, я дам ему попробовать – Breeze

2

Если вы хотите разоблачить данные в классе, вышеупомянутые решения не сократят его. Вы должны пометить __declspec(dllexport) на самом классе в компиляции DLL и __declspec(dllimport) в модуле, который ссылается на DLL.

Общий метод, чтобы сделать это (мастера Microsoft производят подобный код):

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

class MY_API MyClass { 
    ... 
}; 

Затем убедитесь, что EXPORT_API определяется в проекте DLL, и убедитесь, что он не определен в модуле, ссылки на DLL.

Если вы создаете новый проект DLL в Visual C++ с нуля и установите флажок «Экспорт символов», с помощью этой методики будет создан код примера.

Смежные вопросы