[winapi] 使用dllexport从DLL导出函数



Answers

对于C ++:

我只是面临同样的问题,我认为值得一提的是,当使用__stdcall (或WINAPI extern "C"

正如你所知, extern "C"删除了装饰,而不是:

__declspec(dllexport) int Test(void)                        --> dumpbin : ?Test@@YaHXZ

你得到一个符号名称undecorated:

extern "C" __declspec(dllexport) int Test(void)             --> dumpbin : Test

然而, _stdcall (=宏WINAPI,改变了调用约定)也修饰了名字,这样如果我们同时使用,我们可以得到:

   extern "C" __declspec(dllexport) int WINAPI Test(void)   --> dumpbin : _Test@0

extern "C"的好处是丢失,因为符号是装饰(_ _bytes)

请注意,这适用于x86体系结构,因为在x64 忽略__stdcall约定( msdn在x64体系结构上,按照约定,参数在可能的情况下传递到寄存器中,并且随后的参数在堆栈上传递 )。

如果您针对的是x86和x64平台,这尤其棘手。

两种解决方案

  1. 使用定义文件。 但是这迫使你保持def文件的状态。

  2. 最简单的方法:定义宏(参见msdn ):

#define EXPORT comment(linker,“/ EXPORT:”__FUNCTION__“=”__FUNCDNAME__)

然后在函数体中包含以下附注:

#pragma EXPORT

完整示例:

 int WINAPI Test(void)
{
    #pragma EXPORT
    return 1;
}

这将导出x86和x64目标未修饰的函数,同时保留x86的__stdcall约定。 在这种情况下__declspec(dllexport) 不是必需的。

Question

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

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

我希望导出的名称不需要修饰 。 我想使用最标准的调用约定(__stdcall?)。 我想使用__declspec(dllexport) ,而不必使用DEF文件。

例如:

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

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

我试图避免链接器为名称添加下划线和/或数字(字节数?)。

我确定不支持使用相同头文件的dllimport和dllexport。 我不想要任何有关导出C ++类方法的信息,只需要c样式的全局函数。

UPDATE

不包括调用约定(和使用extern“C”)给我的出口名称,我喜欢,但这是什么意思? 无论默认调用约定我得到什么pinvoke(.NET),声明(VB6)和GetProcAddress会期望? (我猜GetProcAddress取决于调用者创建的函数指针)。

我希望这个DLL可以在没有头文件的情况下使用,所以我并不需要很多花哨的#define来使头部可以被调用者使用。

我确定答案是我必须使用DEF文件。




我认为_naked可能会得到你想要的,但它也会阻止编译器为该函数生成堆栈管理代码。 extern“C”导致C风格的名字装饰。 删除,那应该摆脱你的_。 链接器不会添加下划线,编译器会这样做。 stdcall导致参数堆栈大小被追加。

欲了解更多信息,请参阅: http://en.wikipedia.org/wiki/X86_calling_conventions : http://en.wikipedia.org/wiki/X86_calling_conventions http://www.codeproject.com/KB/cpp/calling_conventions_demystified.aspx

更大的问题是你为什么要这样做? 这些重名的名字有什么问题?




Links