2013-05-21 20 views
6

Pochodzę z tła C#/Java, więc staram się dowiedzieć, jak stworzyć C++, która zachowuje się podobnie do C# dll.Jak wyeksportować klasę C++ jako bibliotekę DLL?

Eksperymentowałem z __declspec(dllexport) i __declspec(dllimport), ale udało mi się przekonać go do pracy na statycznych metodach. Jestem pewien, że jest to spowodowane moim ograniczonym zrozumieniem.

Jak mogę wyeksportować klasy w C++ (w całości włączając członków prywatnych) i być w stanie utworzyć ich na końcówce referencyjnej tak jak w C#? Niektóre wskazówki do zasobów/samouczka online również to zrobią.

Zacząłem używać szablonu dll MFC i szczerze mówiąc nie mam pojęcia, do czego jest 90% i dlaczego dziedziczy po CWinApp. Próbowałem oznaczyć tę klasę klasą CCppPracticeLibraryApp, ale nie byłoby już kompilacji.

// CppPracticeLibrary.h : main header file for the CppPracticeLibrary DLL 
// 


#pragma once 

#ifndef __AFXWIN_H__ 
    #error "include 'stdafx.h' before including this file for PCH" 
#endif 

#include "resource.h"  // main symbols 

#ifdef CCppPracticeLibraryApp_EXPORTS 
#define CCppPracticeLibraryApp_API __declspec(dllexport) 
#else 
#define CCppPracticeLibraryApp_API __declspec(dllimport) 
#endif 

// CCppPracticeLibraryApp 
// See CppPracticeLibrary.cpp for the implementation of this class 
// 

class CCppPracticeLibraryApp : public CWinApp 
{ 
public: 
    CCppPracticeLibraryApp(); 
    static CCppPracticeLibraryApp_API void SayHelloWorld(); 
// Overrides 
public: 
    virtual BOOL InitInstance(); 

    DECLARE_MESSAGE_MAP() 
}; 

plik definicji:

//CppPracticeLibrary.cpp: Definiuje procedury inicjalizacji dla DLL.

#include "stdafx.h" 
#include "CppPracticeLibrary.h" 

#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 

#define CCppPracticeLibraryApp_EXPORTS 



BEGIN_MESSAGE_MAP(CCppPracticeLibraryApp, CWinApp) 
END_MESSAGE_MAP() 


// CCppPracticeLibraryApp construction 

CCppPracticeLibraryApp::CCppPracticeLibraryApp() 
{ 
    // TODO: add construction code here, 
    // Place all significant initialization in InitInstance 
} 

void CCppPracticeLibraryApp::SayHelloWorld() 
{ 
    printf("Hello world"); 
} 


// The one and only CCppPracticeLibraryApp object 

CCppPracticeLibraryApp theApp; 


// CCppPracticeLibraryApp initialization 

BOOL CCppPracticeLibraryApp::InitInstance() 
{ 
    CWinApp::InitInstance(); 

    return TRUE; 
} 

Klient/przedstawieniu metoda

// TestConsoleApplication.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include "TestConsoleApplication.h" 
#include "CppPracticeLibrary.h" 

#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 


// The one and only application object 

CWinApp theApp; 

using namespace std; 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 
{ 
    int nRetCode = 0; 

    HMODULE hModule = ::GetModuleHandle(NULL); 

    if (hModule != NULL) 
    { 
     // initialize MFC and print and error on failure 
     if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0)) 
     { 
      // TODO: change error code to suit your needs 
      _tprintf(_T("Fatal Error: MFC initialization failed\n")); 
      nRetCode = 1; 
     } 
     else 
     { 
      // TODO: code your application's behavior here. 
      /*CCppPracticeLibraryApp* testCallingLibrary = new CCppPracticeLibraryApp(); 
      testCallingLibrary->SayHelloWorld();*/ 
      CCppPracticeLibraryApp::SayHelloWorld(); 
     } 
    } 
    else 
    { 
     // TODO: change error code to suit your needs 
     _tprintf(_T("Fatal Error: GetModuleHandle failed\n")); 
     nRetCode = 1; 
    } 

    return nRetCode; 
} 

Chciałbym móc odkomentować następujące linie w powyższym kodzie:

 /*CCppPracticeLibraryApp* testCallingLibrary = new CCppPracticeLibraryApp(); 
     testCallingLibrary->SayHelloWorld();*/ 
+0

Proszę podać kod ... –

+0

@ bash.d Zaktualizowano kodem. – Alwyn

Odpowiedz

4

Od MSDN

Aby wyeksportować wszystkich członków danych publicznych i funkcji składowych w klasie, słowo musi pojawić się po lewej stronie nazwy klasy następująco:

class __declspec(dllexport) CExampleExport : public CObject 
{ ... class definition ... }; 

także , należy wziąć pod uwagę, że jest więcej sposobów na zrobienie tego, na przykład: .DEF -files. Poświęć trochę czasu na przeczytanie objaśnień na stronie MSDN.

+0

czy mogę "nowe" klasy 'CExampleExport' na kodzie odniesienia? przez ten artykuł jest napisane, że będzie eksportował tylko członków publicznych, co oznacza, że ​​instancja klasy nadal będzie miała dostęp do prywatnego członka, tylko że nie będą one dostępne lub nie będą w ogóle importowane, okres? – Alwyn

+2

@Alwyn Eksportuje wszystkie elementy klasy, w tym wewnętrzny kod generowany przez kompilator i dane takie jak vtable, niejawnie wygenerowane funkcje składowe, RTTI, itp. –

+1

Dotyczy to zakresu widoczności. Tworzysz punkty wejścia w bibliotece DLL, z której możesz korzystać Oznacza to, że nie możesz upubliczniać członków prywatnych w ten sposób. –

3

W celu eksportu Wszyscy członkowie klasa możesz zawrzeć declspec w deklaracji jak poniżej.

class __declspec(dllexport) ExportedClass 
{ 
    //.... 
}; 
+0

To jest również odpowiednia odpowiedź :(jeśli tylko mógłbym zaznaczyć, że obie masz właściwą odpowiedź, Ja bym to zrobił Ale dałem +1 – Alwyn

5

Z __declspec (dllexport) i __declspec (dllimport) wystarczy utworzyć rodzaj api, który może być użyty do eksportu metod lub członków z biblioteki dll. Eksportując te metody, można uzyskać do niego dostęp z innego dlll. Możesz utworzyć plik nagłówkowy, w którym zdefiniujesz swoje makro eksportu.

ifdef MYPROJECT_EXPORTS 
     define MYPROJECT_EXPORTS__declspec(dllexport) 
    else 
     define MYPROJECT_EXPORTS__declspec(dllimport) 
    endif 

i kiedy zadeklarować metodę, jeśli chcesz wyeksportować, wystarczy umieścić makro przed deklaracji metody, na przykład:

MYPROJECT_EXPORTS void myMethod(); 

A także trzeba dodać swój symbol do definicji preprocesora (w MS Visual Studio -> Właściwości projektu -> C/C++ -> Preprocesor -> Definicje preprocesora

3

Musisz przeczytać this very interesting article on CodeProject na ten temat.

Zauważ, że jeśli budować DLL z C++ klas w granicach (w tym klas MFC, lub klas STL), klient DLL należy użyć samego VC++ kompilatora wersji i sam smak CRT (np wielowątkowe DLL debugowanie CRT, wielowątkowe wydanie DLL CRT i inne "bardziej subtelne" ustawienia, np. te same ustawienia _HAS_ITERATOR_DEBUGGING) w celu zbudowania plików EXE, które będą korzystać z biblioteki DLL.

Natomiast, jeżeli chcesz wyeksportować interfejs czystym C z DLL (ale można użyć C++ wewnątrz DLL, tak jak Win32 API), lub jeśli budować COM DLL, klienci DLL można używać inna wersja kompilatora VC++ (a nawet różnych CRT) do korzystania z biblioteki DLL.

Ponadto należy zwrócić uwagę na to, co wyżej wymieniony artykuł definiuje jako "C++ Mature Approach" (tj. Za pomocą abstrakcyjnego interfejsu).

Powiązane problemy