使用dllexport从DLL导出函数 [英] Exporting functions from a DLL with dllexport

查看:656
本文介绍了使用dllexport从DLL导出函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个从C ++ Windows DLL导出函数的简单示例。



我想看到标题,cpp文件和def文件(如果绝对需要)。



我希望导出的名称是 未装饰的 。我想使用最标准的调用约定(__stdcall?)。我想使用 __ declspec(dllexport),而不必使用DEF文件。



例如:

  // header 
externC
{
__declspec(dllexport)int __stdcall foo(long bar);
}

// cpp
int __stdcall foo(long bar)
{
return 0;
}

我试图避免链接器添加下划线和/或数字(字节计数?)到名称。我没有支持dllimport和dllexport使用相同的标题,我可以确定,

我不想要任何关于导出C ++类方法的信息,只是c风格的全局函数。



更新



不包括调用约定(使用externC)给出了我喜欢的导出名称,但是这是什么意思?是什么默认调用约定我得到什么pinvoke(.NET),声明(vb6)和GetProcAddress会期望? (我猜GetProcAddress它将取决于调用者创建的函数指针)。



我想要这个DLL没有头文件使用,所以我不是真的需要很多奇特的#define来使头可用于调用者。



我可以回答一下,我必须使用一个DEF文件。

解决方案

如果您想要纯C导出,请使用C项目而不是C ++。 C ++ DLL依赖于所有C ++ isms(命名空间等)的名称控制。您可以通过进入C / C ++ - > Advanced下的项目设置来将代码编译为C,还有一个选项Compile As,它与编译器开关/ TP和/ TC相对应。



在VC ++中导出/导入DLL Lib



您真正想要做的是在标题中定义一个条件宏,将包含在所有您的DLL项目中的源文件:

  #ifdef LIBRARY_EXPORTS 
#define LIBRARY_API __declspec(dllexport)
# else
#define LIBRARY_API __declspec(dllimport)
#endif

然后在您要导出的函数使用 LIBRARY_API

  LIBRARY_API int GetCoolInteger(); 

在您的库构建项目中创建一个定义 LIBRARY_EXPORTS 这将导致您的函数导出为您的DLL构建。



由于 LIBRARY_EXPORTS 不会在项目消耗DLL,当该项目包含您的库的头文件时,将导入所有功能。



如果您的库是跨平台的,您可以在Windows上不能将LIBRARY_API定义为没有:

  #ifdef _WIN32 
#ifdef LIBRARY_EXPORTS
#define LIBRARY_API __declspec(dllexport)
#else
#define LIBRARY_API __declspec(dllimport)
#endif
#elif
#define LIBRARY_API
#endif

使用dllexport / dllimport时,不需要使用DEF文件,如果使用DEF文件,则不需要使用DLLEXPORT / dllimport的。这两种方法以不同的方式完成相同的任务,我相信dllexport / dllimport是两者之间推荐的方法。



从C ++ DLL中导出Unmangled函数,用于LoadLibrary / PInvoke



如果您需要使用LoadLibrary和GetProcAddress,或者也可以从.NET中执行PInvoke,您可以使用 externC与您的dllexport内联。而且由于我们使用GetProcAddress而不是dllimport,我们不需要从上面做ifdef舞蹈,只需一个简单的dllexport:



代码:

  #define EXTERN_DLL_EXPORT externC__declspec(dllexport)

EXTERN_DLL_EXPORT int getEngineVersion(){
return 1 ;
}

EXTERN_DLL_EXPORT void registerPlugin(Kernel& K){
K.getGraphicsServer()。addGraphicsDriver(
auto_ptr< GraphicsServer :: GraphicsDriver>(new OpenGLGraphicsDriver ))
);
}

这里是Dumpbin / exports的导出方式:

 文件转储opengl_plugin.dll 

文件类型:DLL

部分包含以下内容出口opengl_plugin.dll

00000000特征
49866068时间日期戳Sun Feb 01 19:54:32 2009
0.00版本
1 ordinal base
2函数数
2名字数

序数提示RVA名称

1 0 0001110E getEngineVersion = @ ILT + 265(_getEngineVersion)
2 1 00011028 registerPlugin = @ ILT + 35(_registerPlugin)

所以这段代码工作正常:

  m_hDLL = :: LoadLibrary(Topengl_plugin.dll); 

m_pfnGetEngineVersion = reinterpret_cast< fnGetEngineVersion *>(
:: GetProcAddress(m_hDLL,getEngineVersion)
);
m_pfnRegisterPlugin = reinterpret_cast< fnRegisterPlugin *>(
:: GetProcAddress(m_hDLL,registerPlugin)
);


I'd like a simple example of exporting a function from a C++ windows DLL.

I'd like to see the header, the cpp file, and the def file (if absolutely required).

I'd like the exported name to be undecorated. I'd like to use the most standard calling convention (__stdcall?). I'd like the use __declspec(dllexport) and not have to use a DEF file.

For example:

  //header
  extern "C"
  {
   __declspec(dllexport) int __stdcall foo(long bar);
  }

  //cpp
  int __stdcall foo(long bar)
  {
    return 0;
  }

I'm trying to avoid the linker added underscores and/or numbers (byte counts?) to the name.

I'm OK with not supporting dllimport and dllexport using the same header. I don't want any information about exporting C++ class methods, just c-style global functions.

UPDATE

Not including the calling convention (and using extern "C") gives me the export names as I like, but what does that mean? Is whatever default calling convention I'm getting what pinvoke (.NET), declare (vb6), and GetProcAddress would expect? (I guess for GetProcAddress it would depend on the function pointer the caller created).

I want this DLL to be used without a header file, so I don't really need the a lot of the fancy #defines to make the header usable by a caller.

I'm OK with an answer being that I have to use a DEF file.

解决方案

If you want plain C exports, use a C project not C++. C++ DLLs rely on name-mangling for all the C++isms (namespaces etc...). You can compile your code as C by going into your project settings under C/C++->Advanced, there is an option "Compile As" which cooresponds to the compiler switches /TP and /TC.

Exporting/Importing DLL Libs in VC++

What you really want to do is define a conditional macro in a header that will be included in all of the source files in your DLL project:

#ifdef LIBRARY_EXPORTS
#    define LIBRARY_API __declspec(dllexport)
#else
#    define LIBRARY_API __declspec(dllimport)
#endif

Then on a function that you want to be exported you use LIBRARY_API:

LIBRARY_API int GetCoolInteger();

In your library build project create a define LIBRARY_EXPORTS this will cause your functions to be exported for your DLL build.

Since LIBRARY_EXPORTS will not be defined in a project consuming the DLL, when that project includes the header file of your library all of the functions will be imported instead.

If your library is to be cross-platform you can define LIBRARY_API as nothing when not on Windows:

#ifdef _WIN32
#    ifdef LIBRARY_EXPORTS
#        define LIBRARY_API __declspec(dllexport)
#    else
#        define LIBRARY_API __declspec(dllimport)
#    endif
#elif
#    define LIBRARY_API
#endif

When using dllexport/dllimport you do not need to use DEF files, if you use DEF files you do not need to use dllexport/dllimport. The two methods accomplish the same task different ways, I believe that dllexport/dllimport is the recommended method out of the two.

Exporting unmangled functions from a C++ DLL for LoadLibrary/PInvoke

If you need this to use LoadLibrary and GetProcAddress, or maybe doing PInvoke from .NET you can use extern "C" inline with your dllexport. And since we are using GetProcAddress instead of dllimport we don't need to do the ifdef dance from above, just a simple dllexport:

The Code:

#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)

EXTERN_DLL_EXPORT int getEngineVersion() {
  return 1;
}

EXTERN_DLL_EXPORT void registerPlugin(Kernel &K) {
  K.getGraphicsServer().addGraphicsDriver(
    auto_ptr<GraphicsServer::GraphicsDriver>(new OpenGLGraphicsDriver())
  );
}

And here's what the exports look like with Dumpbin /exports:

  Dump of file opengl_plugin.dll

  File Type: DLL

  Section contains the following exports for opengl_plugin.dll

    00000000 characteristics
    49866068 time date stamp Sun Feb 01 19:54:32 2009
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 0001110E getEngineVersion = @ILT+265(_getEngineVersion)
          2    1 00011028 registerPlugin = @ILT+35(_registerPlugin)

So this code works fine:

m_hDLL = ::LoadLibrary(T"opengl_plugin.dll");

m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>(
  ::GetProcAddress(m_hDLL, "getEngineVersion")
);
m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>(
  ::GetProcAddress(m_hDLL, "registerPlugin")
);

这篇关于使用dllexport从DLL导出函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆