【问题标题】:How to export C++ class as a dll? [duplicate]如何将 C++ 类导出为 dll? [复制]
【发布时间】:2013-05-21 18:27:57
【问题描述】:

我来自 C#/Java 背景,所以我试图弄清楚如何创建一个行为类似于 C# dll 的 C++ dll。

我已经尝试过__declspec(dllexport) 和__declspec(dllimport),但我只设法让它在静态方法上工作。我确信这是由于我的理解有限。

如何在 C++ 中导出类(包括私有成员在内的整个类)并能够像使用 C# 一样在引用端实例化它们?一些指向在线资源/教程的指针也可以。

我开始使用 MFC dll 模板,老实说,我不知道其中 90% 的用途以及为什么要从 CWinApp 继承。我尝试用CCppPracticeLibraryApp 标记该类,但它不再编译。

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

定义文件:

//CppPracticeLibrary.cpp : 定义 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;
}

客户端/引用方法

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

我希望能够在上面的代码中取消注释以下行:

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

【问题讨论】:

  • 请出示您的代码...
  • @bash.d 已更新代码。

标签: c++ visual-studio class dllexport


【解决方案1】:

来自MSDN

要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左侧,如下所示:

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

另外,考虑到有更多的方法可以做到这一点,比如.DEF-files。 花点时间阅读 MSDN 网站上的说明。

【讨论】:

  • 我可以在引用代码上new 类CExampleExport 吗?因为通读那篇文章,它说它只会导出public 成员。这是否意味着实例化的类仍然可以访问私有成员,只是它们无法访问或根本不会被导入,期间?
  • @Alwyn 它导出一个类的所有成员,包括内部编译器生成的代码和数据,例如 vtable、隐式生成的成员函数、RTTI 等。
  • 这是关于可见性范围的。您正在创建可以使用的 DLL 的入口点。这只是意味着你不能像这样公开私人成员。
【解决方案2】:

使用 __declspec(dllexport) 和 __declspec(dllimport),您只需创建一种可用于从您的 dll 中导出方法或成员的 api。通过导出此方法,您可以从另一个 dll 访问它。您可以做的是创建一个头文件,您将在其中定义导出宏。

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

当你声明你的方法时,如果你想导出它,你只需要把你的宏放在你的方法声明之前,像这样:

MYPROJECT_EXPORTS void myMethod();

您还必须将符号添加到预处理器定义中(在 MS Visual Studio --> 项目属性 --> C/C++ -->预处理器 --> 预处理器定义中。

【讨论】:

    【解决方案3】:

    为了导出一个类的所有成员,您可以在它的声明中包含declspec,如下所示。

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

    【讨论】:

    • 这也是正确答案 :( 如果我能将你们两个都标记为正确答案,我会的。但我给了 +1。
    【解决方案4】:

    你必须阅读this very interesting article on CodeProject关于这个主题。

    请注意,如果您使用边界处的 C++ 类(包括 MFC 类或 STL 类)构建 DLL,您的 DLL 客户端必须使用相同的 VC++ 编译器版本以及相同的 CRT 风格(例如,多线程 DLL 调试 CRT、多线程 DLL 发布 CRT,以及其他“更微妙”的设置,例如相同的 _HAS_ITERATOR_DEBUGGING 设置)来构建将使用 DLL 的 EXE。

    相反,如果您从 DLL 导出 纯 C 接口(但您可以在 DLL 内部使用 C++,就像 Win32 API 一样),或者如果您构建 COM DLL,您的 DLL 客户端可以使用不同版本的 VC++ 编译器(甚至不同的 CRT)来使用您的 DLL。

    此外,还要注意上述文章定义为 "C++ Mature Approach" 的内容(即使用抽象接口)。

    【讨论】:

      猜你喜欢
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-25
      • 2010-09-06
      • 1970-01-01
      相关资源
      最近更新 更多