问题标签 [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 投票
7 回答
6659 浏览

c++ - 无法从 C 应用程序访问 C++ DLL 中的变量

我坚持修复旧版 Visual C++ 6 应用程序。在我放的 C++ DLL 源代码中

这导致 MyNewVariable 出现在导出表中(很好地未装饰)(如 dumpbin /exports blah.dll 所示)。但是,我不知道如何声明变量以便可以在 C 源文件中访问它。我尝试了各种各样的东西,包括

但这只是给了我一个链接器错误:

未解析的外部符号“__declspec(dllimport) char * MyNewVariable”(__imp_?MyNewVariable@@3PADA)

正如托尼(Tony)所建议的(正如我之前尝试过的那样)会产生不同的预期装饰,但仍未将其删除:

未解析的外部符号 __imp__MyNewVariable

如何编写声明以便可以从 C 应用程序访问 C++ DLL 变量?


答案

正如 botismarius 和其他人(非常感谢所有人)所确定的,我需要链接到 DLL 的 .lib。为了防止名称被破坏,我需要在没有装饰器的情况下(在 C 源代码中)声明它,这意味着我需要使用 .lib 文件。

0 投票
3 回答
10777 浏览

c++ - GCC 使用 __stdcall 编译 dll

当我们在 Visual Studio 2008 中使用 __stdcall 编译 dll 时,dll 中的编译函数名称是。

函数名

虽然当我们使用 GCC 使用 wx-dev-cpp 编译相同的 dll 时,GCC 会附加函数具有的参数数量,所以使用 Dependency walker 的函数的名称看起来像。

FunctionName@numberOfParameters 或 == FunctionName@8

你如何告诉 GCC 编译器从 dll 中的导出符号中删除 @nn?

0 投票
3 回答
650 浏览

visual-studio-2008 - 如何增加 VC9 (MSVC 2008) 中允许的修饰名称长度?

我有一组相当庞大和复杂的程序可以从 VC8 移植到 VC9。其中一个模块有许多分层的 typedef,这会导致编译器生成 C4503 警告(装饰名称被截断)。生成的 LIB 文件将无法正确链接到项目中的其他模块。VC8 对此没有任何问题,这使我得出结论,要么修饰过程已更改为生成更长的名称,要么已减少修饰名称长度的内部限制。克服这个问题的最好方法是什么?

由于遗留代码的原因,MSDN 建议用结构替换 typedefs 是不切实际的。

有问题的 typedef 是(经过清理的代码):

0 投票
5 回答
2448 浏览

visual-c++ - 从 VC8 (VS2005) 到 VC9 (VS2008) 的移植问题是什么?

我继承了一个在 VC8(VS2005)下构建和测试的非常庞大而复杂的项目(实际上是一个由 119 个“项目”组成的“解决方案”,其中大部分是 DLL),我的任务是将它移植到 VC9 (VS2008)。

我使用的移植过程是:

  1. 复制 VC8 .sln 文件并将其重命名为 VC9 .sln 文件。
  2. 复制所有 VC8 项目文件,并将它们重命名为 VC9 项目文件。
  3. 编辑所有 VC9 项目文件,s/vc8/vc9。
  4. 编辑 VC9 .sln, s/vc8/vc9/
  5. 使用 VS2008 加载 VC9 .sln,并让 IDE“转换”所有项目文件。
  6. 修复编译器和链接器错误,直到我得到一个好的构建。

到目前为止,我在最后一步中遇到了以下问题。

1) 修饰名称的计算方式发生变化,导致名称被截断。

这不仅仅是一个警告 ( http://msdn.microsoft.com/en-us/library/074af4b6.aspx )。使用此警告构建的库不会与其他模块链接。应用 MSDN 中给出的解决方案并非易事,而是可行的。我在如何增加 VC9 (MSVC 2008) 中允许的修饰名称长度?

2) 不允许将零分配给迭代器的更改。这是符合规范的,很容易找到并修复这些以前允许的编码错误。不要将零分配给迭代器,而是使用值 end()。

3) for-loop 范围现在符合 ANSI 标准。另一个容易解决的问题。

4) 预编译头文件需要更多空间。在某些情况下,需要更多的空间。我最终使用 /Zm999 来提供最大的 PCH 空间。如果 PCH 内存使用量再次增加,我认为我将不得不完全放弃 PCH,并忍受已经很长的构建时间的增加。

5) 对复制 ctor 和默认 dtor 的要求有所改变。似乎在模板类中,在我还没有完全弄清楚的某些条件下,编译器不再生成默认 ctor 或默认 dtor。我怀疑这是 VC9 中的一个错误,但可能还有其他我做错的事情。如果是这样,我肯定想知道它是什么。

6) sln 和 vcproj 文件中的 GUID 没有改变。这似乎不会以我可以检测到的任何方式影响构建,但仍然令人担忧。

请注意,尽管存在所有这些问题,该项目还是在 VC8 下构建、运行并通过了广泛的 QA 测试。我还将所有更改移植到 VC8 项目中,它们仍然像以前一样愉快地构建和运行(使用 VS2005/VC8)。因此,我为 VC9 构建所需的所有更改至少看起来是向后兼容的,尽管回归测试仍在进行中。

现在解决真正困难的问题:我遇到了 VC8 和 VC9 项目的启动顺序不同。该程序使用了一个仿照 Loki 的小对象分配器,在 Andrei Alexandrescu 的 Book Modern C++ Design中。该分配器使用主程序模块中定义的全局变量进行初始化。

在 VC8 下,这个全局变量是在程序启动的最开始时从模块 crtexe.c 中的代码构造的。在VC9下,第一个执行的模块是crtdll.c,表示启动顺序发生了变化。正在启动的 DLL 似乎通过在全局对象初始化统计信息之前分配和取消分配内存来混淆小对象分配器,这会导致一些虚假的诊断。该程序的运行似乎没有受到实质性影响,但 QA 人员不会允许虚假诊断通过他们。

有没有办法在加载 DLL 之前强制构建全局对象?

我可能会遇到哪些其他移植问题?

0 投票
7 回答
43012 浏览

function - 查找 Dll 函数参数

如何找到未记录的Dll 函数的参数?

我在整个互联网上搜索并最终找到了一种方法:它涉及装饰功能。但是,我找不到获得这些的方法。

任何帮助,将不胜感激。

0 投票
5 回答
8314 浏览

c++ - 使用具有不同编译器版本的 C++ DLL

这个问题与“如何在 VS 版本之间制作一致的 dll 二进制文件?”有关。

  • 我们有使用 VC6 构建的应用程序和 DLL 以及使用 VC9 构建的新应用程序。VC9 应用程序必须使用用 VC6 编译的 DLL,其中大部分是用 C 编写的,一个是用 C++ 编写的。
  • 由于名称修饰/修改问题,C++ 库存在问题。
  • 使用 VC9 编译所有内容目前不是一种选择,因为似乎有一些副作用。解决这些问题将非常耗时。
  • 我可以修改 C++ 库,但它必须使用 VC6 编译。
  • C++ 库本质上是另一个 C 库的 OO 包装器。VC9-app 使用一些静态函数以及一些非静态函数。

虽然静态函数可以用类似的东西来处理

使用非静态方法并不容易。

据我了解,Chris Becke关于使用类 COM 接口的建议对我没有帮助,因为接口成员名称仍将被修饰,因此无法从使用不同编译器创建的二进制文件中访问。我在吗?

唯一的解决方案是使用对象的处理程序编写 C 风格的 DLL 接口,还是我遗漏了什么?在那种情况下,我想,直接使用封装的 C 库可能会更省力。

0 投票
2 回答
894 浏览

c++ - 修改修饰名称 - VS6.0 到 VS2005 迁移

经过几个小时的谷歌搜索,我想是时候问问专家了。我们有一个遗留模块(MS Visual C++ 6.0),我们正在尝试将其移植到 VS 2005。存在许多调用应用程序,因此我们正在尝试(如果可能)保持这些向后兼容。

在代码方面,结果非常简单,几个小时的开发消除了所有编译器错误和大多数警告。

然后我在链接步骤中遇到了一些“未解决的外部符号”错误,这似乎是装饰名称的细微差别。

事实证明,一组错误与 time_t 是 VS2005 中的 64 位结构有关——定义_USE_32BIT_TIME_T修复了这三个。

现在我遇到了两个剩余的错误:

函数定义为

int RC_STATE::my_function(UINT stateId, UINT period, UINT index, UINT paramtype, UINT dpindex, UINT managerId, UINT calctype, UINT status, double *p_val, long *p_isc, CTime *p_time)

看来,在“旧”Visual Studio 下,它对装饰名称很满意

?my_function@RC_STATE@@QAEHIIIIIIIIPANPAJPAVCTime@@@Z

但是现在,VS2005 想要为“CTime”参数包含 ATL 命名空间:

?my_function@RC_STATE@@QAEHIIIIIIIIPANPAJPAVCTime@ATL@@@Z

如果我用这个新的修饰名称更新我的 .DEF 文件,它会编译和链接......耶!除了当我用一些曾经可以工作的代码将那个 DLL 放下时,它抱怨它无法在 DLL 中找到过程入口点(即具有“旧”结构的入口点,没有命名空间)。

有什么建议么?是否有某种关键字,编译器指令可以让我告诉编译器不要将命名空间放在修饰名称中(我知道命名空间很好,但是与需要命名空间的 CTime 类型没有冲突解决冲突)。

是否有任何解决方法可以使修饰名称与旧格式匹配?

非常感谢任何建议。

0 投票
4 回答
150647 浏览

winapi - 使用 dllexport 从 DLL 导出函数

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

我想查看标题、.cpp文件和.def文件(如果绝对需要)。

我希望导出的名称是undecorated。我想使用最标准的调用约定(__stdcall?)。我想要使​​用__declspec(dllexport),而不是必须使用.def文件。

例如:

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

我可以不支持dllimportdllexport使用相同的标题。我不想要任何关于导出 C++ 类方法的信息,只想要 c 样式的全局函数。

更新

不包括调用约定(和使用extern "C")为我提供了我喜欢的导出名称,但这意味着什么?是什么默认调用约定我得到什么 pinvoke (.NET)、声明 (vb6) 和GetProcAddress期望?(我猜GetProcAddress这将取决于调用者创建的函数指针)。

我希望在没有头文件的情况下使用这个 DLL,所以我真的不需要太多花哨的东西#defines来使调用者可以使用头文件。

我可以回答是我必须使用*.def文件。

0 投票
1 回答
258 浏览

c++ - 消除与 C++ 动态库的编译器间不兼容问题

...,对此的跟进。

从我对引用问题的回答中,我了解到:

  • 不同的编译器使用不同的名称修饰,这使得在使用编译器 B 构建的项目中无法使用使用编译器 A 构建的 C++ 动态库,
  • 该库可以构建为静态库,包括项目中的 n 个头文件和源文件或导出符号。(它仍然不会保存重建库以用于不同的编译器。)

根据上述内容仔细查看 SDL,我意识到它的链接有两层:在我的 SDL 项目中,我静态链接到 libSDL.a,而 libSDL.a 又将动态链接到 SDL。 dll,从而消除了不同编译器对不同 .dll 版本的需求。

问题是这是否真的是这种情况以及问题的可行解决方案,还是我错过了什么(以及什么)?

0 投票
4 回答
4311 浏览

visual-c++ - 从 Visual C++ DLL 导出非托管类?

使用 Visual C++ 2008 创建 DLL 时,我有几个选择。我可以创建一个“类库”,据我所知,它实际上会给我一个使用 C++ 的 CLI(托管)扩展的 .Net 库。

因为我不希望这样,并且我假设我需要一个静态 .LIB 文件来链接到另一个 Visual C++ windows 可执行项目,所以我选择“Win32 Project”,并在“应用程序设置”面板上指定一个 C++(没有 MFC ) DLL。

这将创建一个带有 .cpp 文件的项目,该文件应该是我定义“DLL 应用程序的导出函数”的地方。

这似乎也不是我想要的。基本上,我正在寻找的是本机 C++ 等价物,在 C# .NET 中是类库程序集。我想将一些类打包到 DLL 中,然后让 .EXE 项目通过包含 DLL 项目头文件并链接到 .LIB 来使用 DLL 的类来解析引用。

这样做的通常方法是什么?