问题标签 [name-decoration]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
1485 浏览

c++ - 导出未修饰的函数名称

我在这里阅读了几篇关于名称修饰/装饰的文章,并且一直遇到不一致的情况,所以我想我会问一个非常集中的问题,看看会发生什么。

我正在努力提高学习曲线,最终能够在 VS2013 中创建一个 dll,该 dll 可由在非常旧的 Borland C++ 编译器上生成的代码使用。第一步是在VS2013中构建一个可以“说话”的exe和dll。我想要未修饰的函数名称。所以我创建了一个带有一个导出函数的 dll。

我的有限理解是:

  1. extern "C" 表示没有装饰
  2. __declspec(dllexport) 表示导出函数
  3. __cdecl 指定调用签名(参数如何放入堆栈等)

当我使用 DependencyWalker 或 Dumpbin /EXPORTS 检查 dll 时,函数名称未修饰。耶。

这是 exe 中尝试调用 dll 中导出函数的代码:

但是,当我尝试构建 exe 时,出现链接器错误。

请注意,exe 提到_BasicFileOpen。我对此感到困惑。我已经正确地指出了由 dll 构建生成的 lib 文件。我在 exe 中包含了 dll 函数的头文件。为什么链接器不理解导出函数的名称?为什么它认为函数名被修饰了?顺便说一句,使用 .def 文件似乎没有任何区别。

任何意见表示赞赏。

MBB

0 投票
1 回答
1508 浏览

c++ - 如何从 DLL 导出中删除下划线

我想替换一个我没有完整源代码(但函数声明)的 DLL。应用程序在运行时加载此 DLL 并GetProcAddress使用(所有)函数名称进行调用。(所以我必须将函数命名为完全相同)。

我创建了一个新的 DLL(在 MS VC2013 中)并编写了函数。但是我在正确导出它们时遇到问题。

在原始 DLL 中,它们被定义,_stdcall但它们的名称不以下划线开头。

如果我像这样在 .def 文件中指定名称,testfunc@4=testfunc则 @ 后面的所有内容都将被删除。

如何在 VS2013 中指定我想要一个 DLL 导出,例如testfunc@4

0 投票
2 回答
1240 浏览

winapi - 当名称可能被修饰时使用 GetProcAddress

GetProcAddress()在 32 位 DLL 上使用的正确方法是什么?在win32上,共有三种调用约定,cdecl、stdcall和fastcall。如果 DLL 中的函数是foo他们将通过以下方式装饰名称_foo_foo@N并且@foo@N.

但是如果 dll 的作者使用了 .def 文件,那么导出的名称将被更改为只是“foo”而没有任何修饰。

这给我带来了麻烦,因为如果我想foo从使用 stdcall 的 dll 加载,我应该使用修饰名称:

或未装饰的:

? 我应该猜吗?我查看了许多 32 位 DLL 文件(stdcall 和 cdecl),它们似乎都导出了未修饰的名称。但是你能假设情况总是如此吗?

0 投票
1 回答
456 浏览

c - C中的名称装饰

是否有任何标准的授权名称装饰?

据我所知,大多数(全部?)符合标准的实现都会在每个导出符号的名称中添加下划线前缀。这是由 C、POSIX 或其他标准保证的吗?

0 投票
1 回答
641 浏览

c++ - 函数的修饰名称生成不当

我正在尝试使用 Visual Studio 2017(从 Visual Studio 6.0 升级)将一些第三方 C++ 代码编译到我的 32 位 C++ 应用程序中。我有来自第三方的 .h 文件和 .lib 文件。链接器正在查找库,但没有找到其中包含的修饰名称。这似乎是因为编译器正在用“char”替换“__int8”。

链接器错误是:

该函数在 .h 中定义:

API_RETURN_TYPE 在 .h 中定义:

使用 dumpbin /exports,我可以看到我的 lib 和关联的 dll 导出 Check_The_Thing:

使用 undname,我可以看到 lib 中的修饰名称正确评估:

但是编译器生成的修饰名称没有正确评估(基于代码):

根据https://en.wikiversity.org/wiki/Visual_C%2B%2B_name_mangling,YACXZ 中的“C”计算为“signed char”,“_D”计算为“__int8”。我无法弄清楚为什么编译器将 API_RETURN_TYPE 解释为“char”而不是“__int8”。很明显,lib/dll 导出应该有“_C”而不是“_D”,因为 API_RETURN_TYPE 是“签名的 __int8”,而不仅仅是“__int8”。

我摆弄了一堆编译器设置,但没有运气。正如这里所建议的(在 dll 中找不到修饰的函数名称),我确保我使用的是 MBCS 而不是 Unicode(之前未设置),但这也没有什么区别。

专门将 API_RETURN_TYPE 定义为 __int8 没有区别,只是将“C”更改为“D”(进度!),同样 undname 将返回类型显示为“char”而不是“signed char”。将函数定义的返回类型更改为 __int8 与更改 API_RETURN_TYPE 的效果相同。

所以,我的问题是:如何强制编译器使用“__int8”(或“_D”)而不是 char(“D”)正确定义我的导出?

旁注:在使用 __int16、__int32 和 __int64 的情况下,链接器错误是相同的。

编辑:实际上,该库定义了 __int64 类型,但我没有使用任何类型。没有任何 __int64 链接器错误。

0 投票
0 回答
56 浏览

c++ - Visual C++ 2015 不生成前导“_”

我现在创建 dll 已经很长时间了,但是我对我的新项目中出现的一个问题有点好奇,第一个带有VS C++ 2015.

它没什么特别的,一个简单的 C++ 项目,创建一个 windows 32/64 位 dll。我正在像这样将我的函数导出为“C”(没有 DEF 文件):

但是我的应用程序加载 dll 失败了Can not find _foo()。使用 Dependency Walker 检查 dll 显示我foo()已导出,但没有强制性的_.

我找不到对创建导出函数名称有影响的编译器/链接器选项。

0 投票
2 回答
383 浏览

c++ - 将英特尔 Visual Fortran 程序链接到 C++ 函数时出现问题

我正在尝试将一个非常简单的 C++ 函数链接到一个非常简单的 Intel Visual Fortran 程序。

Fortran 程序在一个名为 VFTestBed.f90 的文件中如下所示):

Fortran 接口块如下所示(在名为 interfaces.f90 的文件中):

C++ 函数如下所示(在名为 cppresponder.cpp 的文件中):

我在谷歌上研究了这个问题,并尝试了各种设置、声明、装饰等的几十种排列和组合,但都无济于事。事实上,许多帖子都很长而且相当复杂,而且往往似乎没有得出一个成功的结论。

除其他外,我尝试过:

  1. 使 C++ 代码成为 .LIB
  2. 使 C++ 代码成为 .DLL
  3. 使用各种形式的 !DEC$ATTRIBUTES DECORATE, ALIAS: "SimpleTest1"
  4. 使用 BIND(C, ...)
  5. 使用普通别名
  6. 使用修饰别名
  7. 使用 DUMPBIN 查看 .DLL 中的符号
  8. 使用前导外部“C”
  9. 编译为 C 代码(禁用所有 C++ 结构)

还有很多其他的东西。我已经尝试了所有应该对其他海报有用的东西,但绝对没有运气。

无论我做什么,我都会收到一条链接器错误消息 LNK2019,关于函数 _MAIN__ 中引用的未解析的外部符号 _SIMPLETEST1

根据英特尔网站,我在 CppResponder.DLL 中添加了,就像在源文件中添加一样。

如果重要的话,我正在使用适用于 Windows 的 Visual Studio Enterprise 2017 和 Intel Parallel Studio XE 2016 Update 4 composer Edition,它们都在 64 位 Windows 8.1 机器上运行。

假设 Intel Fortran 确实可以调用 C++ 函数(我假设它可以),那么我一定是在某处缺少开关或设置。我已经使用 Visual Studio 提供的默认值设置了 Fortran 和 C++ 项目。两个项目都设置为 Release | x86。

当然,这真的不是那么难的事情。我在这上面花了大约 12 个小时,但没有什么可展示的。我在 Fortran 方面拥有数十年的经验,但对 C++ 还是很陌生。

有没有人这样做过,并愿意带我了解你是如何做到的?

提前致谢,

鲍勃·基泽

0 投票
0 回答
684 浏览

c++ - 在 Visual Studio 中链接到 C++(32 位)中去修饰的 DLL 名称时出现问题

我有一个 C++ 中的 DSP 函数库,我想在运行时动态链接到它们。我正在使用PDLL.h方法将我的类(例如 FFT)包装到 C 风格的函数中,并在其他 C++ 应用程序中动态加载它们。我想在 .NET 应用程序和 COM 组件中使用这些函数,所以我必须使用__stdcall32 位构建中的名称来装饰名称。

为了取消装饰名称,我使用了这里提到的技巧:C++ DLL Export: Decorated/Mangled names(wqw 的答案,第 2 下)。例如,在我的库的 .h 文件中,我声明了我的包装函数:

这确实有效,当我使用依赖项walker 查看 dll 时,我看到 DoFFT 和 _DoFFT@12 都有一个条目。

我遇到的问题是,当我尝试构建一个链接到该库的项目时(动态地,在运行时,根本不使用 .lib 文件),我的 dll 中的所有函数都会出现链接器错误,即:

我不明白为什么会这样。首先,符号 _DoFFT@12 确实存在(根据dependency walker),其次,为什么链接器首先要寻找它?我在运行时链接到它,而不是在编译时,所以我的项目怎么知道这个符号?

所有函数都使用相同的宏链声明,这些宏可以简化为(例如):

在客户端声明与库无关。

0 投票
0 回答
382 浏览

c++ - __FUNCDNAME__ 返回错误的修饰函数名

函数签名是:

函数内使用的__FUNCDNAME__宏返回修饰函数名:

  • 图像内的真实函数名:?Test@@YGXPADH@Z
  • __FUNCDNAME__ 返回:?Test@@YGXPADH@Z

/clr选项打开时(项目 > 属性 > 常规 > 公共语言运行时支持 > /clr)__FUNCDNAME__ 宏不返回真正的修饰函数名称:

  • 图像内的真实函数名:?Test@@YGXPADH@Z
  • __FUNCDNAME__ 返回:?Test@@ $$F YGXPADH@Z __FUNCDNAME__ 宏不返回真正的修饰函数名。

这使得无法使用#pragma 注释指令直接从代码中导出 DLL 中的函数而无需名称修饰:

返回链接器错误 LNK1242 '?Test@@$$FYGXPADH@Z' 是无效的导出符号名称。

0 投票
0 回答
94 浏览

c++ - 为什么微软链接器修改修饰的导出名称?

我正在尝试使用此处推荐的“wrappit”工具制作代理 dll 。工具“wrappit”正确创建为 .cpp:

作为随附的 .def 文件:

但是在我构建了生成的库之后,构建的 dll 中所有导出函数的名称似乎都在参数描述开始时被截断了。所以??0CFileFormat@@QAE@XZ转入??0CFileFormat?GetSkipListingForSPlanner@EnvironVar@@SAKXZ转入?GetSkipListingForSPlanner@EnvironVar等等。结果,由于缺少必要的导出,我的代理 dll 无法加载。为什么会发生这种情况,我应该怎么做才能解决它?