从非托管的C++创建DLL

5
我目前有一个用非托管C++编写的控制台应用程序,源代码包括入口点main和其他一些函数。我需要从这个代码创建一个DLL,以便我可以从其他项目使用它,特别是从托管C++。 (还有一个问题:我是否需要为此编写包装器类?)
由于我对托管/非托管C++和创建DLL知之甚少,所以我按照教程this tutorial来操作,仅使用VS2010(没有CMake)就成功运行了一个简单的Hello World DLL。
然而,我的这个项目有很多依赖项(例如Point Cloud Library),因此我通常使用CMake生成Visual Studio 2010解决方案,然后构建成可执行文件,如PCL Tutorial中所述。 我该如何使用CMake构建一个能够生成DLL的VS2010项目?
总结我的问题:
  1. 我有一个未管理的C++代码项目,需要很多依赖项。
  2. 我想从这个代码创建一个DLL,可以从托管的C++中调用。

额外信息: Windows 7,Visual Studio 2010 Ultimate,CMake 2.8.10.2

编辑: 我使用了更改过的CMake命令行,它按预期工作。 这是我已添加到我的头文件中的内容,我在正确的轨道上吗?

MyCode.h

#ifdef MyLib_EXPORTS
#define API_DECL __declspec( dllexport )
#else 
#define API_DECL __declspec( dllimport )

#include <iostream>
#include <pcl/...>
etc...

API_DECL void myFirstFunction();
API_DECL void mySecondFunction();
#endif

MyCode.cpp:我没有对源文件进行任何更改,我需要做出任何更改吗?


你的 #endif 应该在包含 iostream 之前关闭。 - Johannes S.
我想我的DLL已经可以工作了。现在需要处理未托管/托管的情况。谢谢! - hjweide
1个回答

5
很抱歉,我无法帮助你处理托管代码部分,但是这是如何在CMake中创建DLL的方法:

首先,不要使用

`ADD_EXECUTABLE( YourLib SHARED yourclass.cpp yourclass.h )` 

在你的 CMakeLists.txt 文件中,使用以下内容:
`ADD_LIBRARY( YourLib SHARED yourclass.cpp yourclass.h )`

这将配置解决方案以创建 DLL 而不是可执行文件。
然而,要能够在您的项目中使用此 DLL,您需要导出要使用的符号。为此,您需要在类和/或函数声明中添加 "__declspec( dllexport )"。构建库将产生两个文件,一个是 ".dll",另一个是 ".lib"。后者是所谓的导入库,在您想要在其他项目中使用此库时需要。".dll" 将在运行时需要。
然而:当您要使用您的库时,您需要使用 "__declspec( dllimport )"(而不是 "dllexport")。为避免使用两个头文件,通常的做法是使用预处理器。CMake 实际上通过在您的库项目中提供 "YourLibrary_EXPORTS" 宏定义来帮助您。
总结一下:
#ifndef YOUR_CLASS_H
#define YOUR_CLASS_H

#ifdef YourLib_EXPORTS
#define API_DECL __declspec( dllexport )
#else 
#define API_DECL __declspec( dllimport )
#endif

class APIDECL YourClass  {
   void foo();
   void bar();
};

#endif // YOUR_CLASS_H

编辑: 如果您想从C(和能够使用C函数的语言)中使用这些函数,您应该在声明中添加extern "C" {

extern "C" {
    API_DECL void myFirstFunction();
    API_DECL void mySecondFunction();
}

谢谢!我只是想检查一些事情。这是否意味着我的函数声明,例如mainFunc(int a)应该更改为__declspec(dllexport) mainFunc(int a) - hjweide
不,你不会导出你的 main 函数(至少不是 mainWinMain)。这将与可执行文件中的主函数发生冲突,该文件将链接到此库。但是,如果您需要在加载 dll 时调用特定的代码,请查看 http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx - Johannes S.
1
抱歉在之前的评论中弄错了链接:这是正确的 DllMain - Johannes S.
好的,我想我明白了。这意味着我只需要重新声明那些我想要从外部访问的函数?在我的情况下,只有main函数是可访问的就足够了,所以我应该选择使用DllMain吗? - hjweide
如果你想在外部使用一个函数(它是一个库),我强烈建议给你的函数取一个不同的名字。然后只需用那个名字调用它即可。 - Johannes S.
是的,在考虑了一下之后,我意识到这样做更有意义。我已经编辑了我的问题以提供一些额外的清晰度,你能否请检查一下我是否仍然正确地做着?非常感谢你迄今为止的帮助! - hjweide

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接