我来自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();*/
答案 0 :(得分:6)
来自MSDN
要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左侧,如下所示:
class __declspec(dllexport) CExampleExport : public CObject
{ ... class definition ... };
另外,请考虑有更多方法可以执行此操作,例如.DEF
- 文件。
花些时间阅读MSDN网站上的解释。
答案 1 :(得分:6)
使用__declspec(dllexport)和__declspec(dllimport),您只需创建一种api,它可用于从您的dll导出方法或成员。通过导出此方法,您可以从另一个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 ++ - >预处理器 - >预处理器定义。
答案 2 :(得分:4)
为了导出课程的所有成员,您可以在其中包含declspec
声明,如下所示。
class __declspec(dllexport) ExportedClass
{
//....
};
答案 3 :(得分: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接口(但您可以在内部使用C ++ ,就像Win32 API一样),或者如果您构建< strong> COM DLL,您的DLL客户端可以使用不同版本的VC ++编译器(甚至不同的CRT)来使用您的DLL。
此外,还要注意上述文章定义为"C++ Mature Approach"的内容(即使用抽象界面)。