Visual C++:在 def 文件中导出修饰函数名称

Posted

技术标签:

【中文标题】Visual C++:在 def 文件中导出修饰函数名称【英文标题】:Visual C++: Exporting decorated function name in a def file 【发布时间】:2011-09-14 08:16:53 【问题描述】:

我想在 def 文件中导出修饰函数名,如下所示:

LIBRARY Example
EXPORTS
??0__non_rtti_object@std@@QAE@ABV01@@Z=myfunc @1

问题是链接器在第一个 @-sign 处去掉了函数名,只放置 "??0__non_rtti_object" 到导出表中。我现在的问题是,如果有办法包括 @-字符也是?我使用 Visual Studio 2010。也许有人可以帮助我。

提前致谢,汉内斯。

【问题讨论】:

我很好奇为什么您首先要使用 .DEF 文件...您能详细说明一下吗?...您为什么不使用 @987654322 @/__declspec(dllimport) 限定词? 感谢您的回答。问题是我需要有一个 dll 导出的特殊名称。我认为给出此类名称的唯一方法是使用 def 文件。 dllexport、dllimport 限定符仅导出/导入源代码中命名的函数。但我需要重命名这些函数。另一个原因是,您不能在 C 文件中使用 @-signs,而是像在修饰 C++ 函数时那样导出它。 @ymett 我已经尝试使用引号,但它不起作用。你让它工作了吗?如果是这样,您使用的是什么版本? 特殊名称是什么意思?带有“@”等特殊字符的名称? . . .或者,如果您只想重命名该函数,那么您不将所需的函数用另一个具有您想要的名称的函数包装起来吗? . . .是否要删除装饰(如果是,则使用 extern "C" 限定符)? . . .你的目标还不清楚...... :-( 是的,我的意思是像'@'这样的特殊字符。抱歉,如果我的问题不清楚。 对不起,我的回答错了。但是,我尝试了?f@@YAHN@Z @2 的函数int f(double),它运行良好。你的函数的实际签名是什么? 【参考方案1】:

序言

您没有回答我关于使用 .DEF 文件的评论,所以我认为您一定不熟悉 dllexportdllimport 限定符。有了它们,.DEF 文件就不需要导出符号了。

如果特别需要使dllimport/dllexport 功能的使用无效的 .DEF 文件,请忽略以下内容。

dllimport/dllexport如何使用?

在您的公共标头(例如,public.hpp)中,写如下内容:

#ifdef MY_PROJECT_EXPORTS
   #define MY_PROJECT_API __declspec(dllexport)
#else
   #define MY_PROJECT_API __declspec(dllimport)
#endif

这样,宏 MY_PROJECT_API 将启用您的符号的导出/导入。例如,稍后在同一个public.hpp中,可以声明:

// A global variable
MY_PROJECT_API int myGlobalVariable ;

// A function
MY_PROJECT_API void my_function() ;

// A class or struct
class MY_PROJECT_API MyClass

   public :
      int i;
      virtual int foo() ;
      // etc.
 ;

然后,你需要做的是,在你的库的项目选项中,定义MY_PROJECT_EXPORTS:这样,当你编译你的库时,上面的符号被声明为dllexport,当其他人包含你的public.hpp 标头,上面的符号将是dllimport

如果您的代码是跨平台的(dllimport/dllexport 是 MS 编译器功能),只需将上面的定义包装在编译器测试周围。例如:

#ifdef _MSC_VER
   // For MS Visual Studio
   #ifdef MY_PROJECT_EXPORTS
      #define MY_PROJECT_API __declspec(dllexport)
   #else
      #define MY_PROJECT_API __declspec(dllimport)
   #endif
#else
   // For other compilers
   #define MY_PROJECT_API
#endif

关于 .DEF 文件?

之前使用了 .DEF 文件,当时可导出的 C 函数在 Visual Studio 上仍然是“可行的方法”。

为了强类型安全,C++ 装饰了它的符号。

缺点是每个编译器都有自己的装饰方案(这在 12 年的开发中从未困扰过我),而且找到符号的准确装饰名称不会很痛苦。

但这样做的好处是:

    您现在可以导出重载/命名空间函数/符号 参数类型是 ABI 的一部分,这意味着链接器可以验证您没有搞砸或欺骗您的类型

dllimportdllexport 功能具有以下优点:

    它可以在源代码级别完成导出,而不是使用另一个项目文件 程序员现在可以忽略特定的装饰方案(通常只对链接器感兴趣),同时受益于扩展至链接器的 C++ 的强类型安全性。

来源

有关详细信息,请参阅:

__declspec:http://msdn.microsoft.com/en-us/library/dabb5z75.aspx dllexportdllimport:http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx 在 C++ 类中使用 dllimportdllexport:http://msdn.microsoft.com/en-us/library/81h27t8c.aspx

【讨论】:

以上是关于Visual C++:在 def 文件中导出修饰函数名称的主要内容,如果未能解决你的问题,请参考以下文章

动态链接库中导出模板函数

使用 def 文件从可执行文件中导出函数

我的 C# win 表单应用程序在内部调用批处理脚本,如何在 Visual Studio 中导出时对最终用户隐藏它?

在 SwiftUI 中导出文件时显示 ProgressView

是否可以在 DLL 中导出具有 C 链接的 C++ 成员方法?

Visual Studio 2010 中的 C++ 访问修饰符自动缩进慢慢让我发疯 - 可以更改吗?