2013-05-21 29 views
6

我来自C#/ Java背景,所以我想弄清楚如何创建一个类似于C#dll的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();*/ 
+0

请显示您的代码... –

+0

@ bash.d使用代码更新。 – Alwyn

回答

4

MSDN

要导出所有的类中的公共数据成员和成员函数,关键字必须按如下方式出现在类名的左边,请考虑有更多的方法来做到这一点,比如.DEF -files。 花点时间阅读MSDN网站上的解释。

+0

我可以在参考代码上'new'类CExampleExport吗?因为阅读通过那篇文章,它说它只会输出'public'成员,这是否意味着实例化的类将仍然可以访问私有成员,只有它们不会被访问,或者根本不会被导入? – Alwyn

+2

@Alwyn它导出一个类的所有成员,包括内部编译器生成的代码和数据,例如vtable,隐式生成的成员函数,RTTI等。 –

+1

这是关于可见性范围。您正在创建可用于DLL的入口点这只意味着你不能像这样公开私人成员。 –

3

为了导出的所有成员你可以在下面的声明中加入declspec

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

另外:

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

这也是正确的答案:(如果只有我可以标记你有正确的答案,我会的,但我给了+1。 – Alwyn

5

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

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

您必须阅读​​3210关于此主题。

需要注意的是,如果你在边界(包括MFC类,或STL类)与C++类建立一个DLL,您的DLL的客户端必须使用同一VC++编译器版本相同CRT的味道(如多线程DLL调试CRT,多线程DLL释放CRT和其他“更微妙”的设置,例如相同的设置)来构建将使用该DLL的EXE。

相反,如果从DLL导出一个纯C接口(但你可以使用C++ 的DLL,就像Win32 API的),或者如果你建立COM的DLL,你的DLL客户端可以使用一个不同版本的VC++编译器(甚至不同的CRT)来使用您的DLL。此外,还要注意上述文章定义为"C++ Mature Approach"(即使用抽象接口)。