Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to export C++ class as a dll? [duplicate]

I came from a C#/Java background, so I'm trying to figure out how to create a C++ dll that behaves similar to a C# dll.

I have experimented with __declspec(dllexport) and __declspec(dllimport), but I have only managed to get it to work on static methods. I am sure this is due to my limited understanding.

How can I export classes in C++ (in its entirety including private members) and be able to instantiate them on the referencing end as I would with C#? Some pointer to an online resources/tutorial will also do it.

I started using the MFC dll template, and honestly I have no idea what 90% of them is for and why I'm inheriting from CWinApp. I tried to tag the class with CCppPracticeLibraryApp but it would no longer compile.

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

the definition file:

//CppPracticeLibrary.cpp : Defines the initialization routines for the 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;
}

The client/referencing method

// 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;
}

I would like to be able to uncomment the following lines in the above code:

        /*CCppPracticeLibraryApp* testCallingLibrary =  new CCppPracticeLibraryApp();
        testCallingLibrary->SayHelloWorld();*/
like image 617
Alwyn Avatar asked May 21 '13 06:05

Alwyn


4 Answers

From MSDN

To export all of the public data members and member functions in a class, the keyword must appear to the left of the class name as follows:

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

Also, consider that there are more ways to do this, like .DEF-files. Take your time to read through the explanations on the MSDN-site.

like image 51
bash.d Avatar answered Nov 06 '22 00:11

bash.d


With __declspec(dllexport) and __declspec(dllimport) you just create kind of an api which can be used to export methods or members from your dll. By exporting this methods you can access it from another dlll. What you can do is to create a header file where you will define your export macro.

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

and when you declare your method, if you want to export it, you just need to put your macro before your method declaration, like this:

MYPROJECT_EXPORTS void myMethod();

And also you have to add your symbol into the Preprocesor Definitions ( in MS Visual Studio --> Project Properties --> C/C++ -->Preprocessor --> Prerocessor Definitions.

like image 34
cosmarc Avatar answered Nov 05 '22 23:11

cosmarc


In order to export all members of a class you can include the declspec in it's declaration like below.

class __declspec(dllexport) ExportedClass
{
    //....
};
like image 42
Captain Obvlious Avatar answered Nov 05 '22 23:11

Captain Obvlious


You must read this very interesting article on CodeProject on this subject.

Note that if you build a DLL with C++ classes at the boundaries (including MFC classes, or STL classes), your DLL client must use the same VC++ compiler version and the same CRT flavor (e.g. multithreaded DLL debug CRT, multithreaded DLL release CRT, and other "more subtle" settings, e.g. same _HAS_ITERATOR_DEBUGGING settings) to build the EXEs that will use the DLL.

Instead, if you export a pure C interface from the DLL (but you can use C++ inside the DLL, just like Win32 APIs), or if you build COM DLLs, your DLL clients can use a different version of VC++ compiler (and even different CRTs) to use your DLL.

Moreover, pay attention also to what the aforementioned article defines as "C++ Mature Approach" (i.e. using an abstract interface).

like image 25
Mr.C64 Avatar answered Nov 05 '22 23:11

Mr.C64