Eksportowanie i importowanie przy użyciu makra AFX_EXT_CLASS

Biblioteki DLL rozszerzeń MFC używają AFX_EXT_CLASS makra do eksportowania klas; pliki wykonywalne łączące się z biblioteką DLL rozszerzenia MFC używają makra do importowania klas. W makrze AFX_EXT_CLASS pliki nagłówkowe używane do kompilowania biblioteki DLL rozszerzenia MFC mogą być używane z plikami wykonywalnymi, które łączą się z biblioteką DLL.

W pliku nagłówkowym biblioteki DLL dodaj słowo kluczowe AFX_EXT_CLASS do deklaracji klasy w następujący sposób:

class AFX_EXT_CLASS CMyClass : public CDocument
{
// <body of class>
};

To makro jest definiowane przez MFC tak, jak __declspec(dllexport) w przypadku, gdy symbole _AFXDLL preprocesora i _AFXEXT są zdefiniowane. Jednak makro jest definiowane tak, jak __declspec(dllimport) w przypadku, gdy _AFXDLL jest zdefiniowane i _AFXEXT nie jest zdefiniowane. Po zdefiniowaniu symbol _AFXDLL preprocesora wskazuje, że współużytkowana wersja MFC jest używana przez docelowy plik wykonywalny (biblioteka DLL lub aplikacja). Gdy zarówno plik wykonywalny, jak _AFXDLL i _AFXEXT są zdefiniowane, oznacza to, że docelowy plik wykonywalny jest biblioteką DLL rozszerzenia MFC.

Ponieważ AFX_EXT_CLASS jest definiowany jako __declspec(dllexport) podczas eksportowania z biblioteki DLL rozszerzenia MFC, można eksportować całe klasy bez umieszczania nazw ozdobionych dla wszystkich symboli tej klasy w pliku .def.

Chociaż można uniknąć tworzenia pliku .def i wszystkich nazw ozdobionych dla klasy przy użyciu tej metody, utworzenie pliku .def jest bardziej wydajne, ponieważ nazwy mogą być eksportowane przez porządkowe. Aby użyć metody eksportowania pliku .def, umieść następujący kod na początku i na końcu pliku nagłówka:

#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA

Uwaga

Podczas eksportowania funkcji wbudowanych należy zachować ostrożność, ponieważ mogą one powodować konflikty wersji. Funkcja śródliniowa jest rozszerzana w kod aplikacji; W związku z tym, jeśli później ponownie napiszesz funkcję, nie zostanie zaktualizowana, chyba że sama aplikacja zostanie ponownie skompilowana. Zwykle funkcje bibliotek DLL można aktualizować bez ponownego kompilowania aplikacji, które ich używają.

Eksportowanie poszczególnych składowych w klasie

Czasami możesz wyeksportować poszczególne elementy członkowskie klasy. Na przykład w przypadku eksportowania klasy pochodnej CDialogmoże być konieczne wyeksportowanie konstruktora i wywołania DoModal . Możesz użyć AFX_EXT_CLASS dla poszczególnych członków, których musisz wyeksportować.

Przykład:

class CExampleDialog : public CDialog
{
public:
   AFX_EXT_CLASS CExampleDialog();
   AFX_EXT_CLASS int DoModal();
   ...
   // rest of class definition
   ...
};

Ponieważ nie eksportujesz już wszystkich elementów członkowskich klasy, możesz napotkać dodatkowy problem ze względu na sposób działania makr MFC. Kilka makr pomocników MFC faktycznie deklaruje lub definiuje elementy członkowskie danych. W związku z tym te elementy członkowskie danych muszą być również eksportowane z biblioteki DLL.

Na przykład DECLARE_DYNAMIC makro jest definiowane w następujący sposób podczas kompilowania biblioteki DLL rozszerzenia MFC:

#define DECLARE_DYNAMIC(class_name) \
protected: \
   static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
   static AFX_DATA CRuntimeClass class##class_name; \
   virtual CRuntimeClass* GetRuntimeClass() const; \

Wiersz rozpoczynający się od statycznego AFX_DATA oznacza obiekt statyczny wewnątrz klasy. Aby poprawnie wyeksportować tę klasę i uzyskać dostęp do informacji w czasie wykonywania z pliku wykonywalnego klienta, należy wyeksportować ten obiekt statyczny. Ponieważ obiekt statyczny jest zadeklarowany za pomocą modyfikatora AFX_DATA, należy zdefiniować AFX_DATA__declspec(dllexport) go tylko podczas kompilowania biblioteki DLL i zdefiniować go tak, jak __declspec(dllimport) podczas kompilowania pliku wykonywalnego klienta. Ponieważ AFX_EXT_CLASS jest już zdefiniowany w ten sposób, wystarczy ponownie zdefiniować AFX_DATA definicję tak samo jak AFX_EXT_CLASS w przypadku definicji klasy.

Przykład:

#undef  AFX_DATA
#define AFX_DATA AFX_EXT_CLASS

class CExampleView : public CView
{
   DECLARE_DYNAMIC()
   // ... class definition ...
};

#undef  AFX_DATA
#define AFX_DATA

Ponieważ MFC zawsze używa symbolu AFX_DATA na elementach danych, które definiuje w swoich makrach, ta technika działa w przypadku wszystkich takich scenariuszy. Na przykład działa dla elementu DECLARE_MESSAGE_MAP.

Uwaga

Jeśli eksportujesz całą klasę, a nie wybrane elementy członkowskie klasy, statyczne składowe danych zostaną automatycznie wyeksportowane.

Co chcesz zrobić?

Co chcesz dowiedzieć się więcej?

Zobacz też

Eksportowanie z biblioteki DLL