如何将c++类导出为dll
How to export C++ class as a dll?
我来自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 failedn"));
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 failedn"));
nRetCode = 1;
}
return nRetCode;
}
我希望能够取消上述代码中以下几行的注释:
/*CCppPracticeLibraryApp* testCallingLibrary = new CCppPracticeLibraryApp();
testCallingLibrary->SayHelloWorld();*/
From MSDN
要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左侧,如下所示:
class __declspec(dllexport) CExampleExport : public CObject
{ ... class definition ... };
另外,考虑有更多的方法可以做到这一点,比如.DEF
-files。请慢慢阅读msdn网站上的解释。
使用__declspec(dllexport)和__declspec(dllimport),您只需创建一种api,可用于从dll导出方法或成员。通过导出这些方法,您可以从另一个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++ ->预处理器->预处理器定义)
为了导出一个类的所有成员,你可以在它的声明中包括declspec
,如下所示。
class __declspec(dllexport) ExportedClass
{
//....
};
您必须阅读关于这个主题的CodeProject的这篇非常有趣的文章。
请注意,如果您在边界(包括MFC类或STL类)构建带有 c++类的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++成熟方法"(即使用抽象接口)。
- 挂起和取消挂起一个文件DLL
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 导入库可以跨dll版本工作吗
- 从C++dll访问C#中的一行主要参数
- 链接到自行创建的dll失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- C++:将外部库链接到dll库
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 不同的Visual Studio版本中缺少.dll
- 从DLL中删除类的实例
- 如何包装第三方DLL在R中使用
- 使用c#访问c++dll中带有char*参数的函数时发生AccessViolationException
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Python ctypes:不会按预期加载 dll
- 在 C++/CLI 中将 .NET 事件从一个 DLL 引发到另一个 DLL