x64 DLL 导出函数名称

2024-07-01

我正在尝试将 32 位 dll(和应用程序)移植到 64 位,并且我成功地构建了它而没有错误。当尝试使用我的 64 位应用程序加载它时,我注意到导出的函数名称不同。这就是我导出函数的方式:

#ifdef __cplusplus
extern "C" {
#endif

__declspec(dllexport) long __stdcall Connect(char * name, long size);

#ifdef __cplusplus 
}
#endif

在 Dependency Walker 中,导出的函数具有以下格式:

32-bit: _Connect@8

64-bit: Connect

在使用 dll 的应用程序中,我显式加载 dll(LoadLibrary 成功),但 GetProcAddress 对于 64 位失败,因为它找不到具有所提供名称的函数。

在我们的应用程序中,我保留函数名称如下:

#define ConnectName "_Connect@8"
...
GetProcAddress(Dll, ConnectName);

所以我想知道是否可以为 32 位和 64 位 dll 导出相同的函数名称,或者这是一个坏主意?或者我需要在我的应用程序中执行以下操作:

#if _WIN64
#define ConnectName "Connect"
#else
#define ConnectName "_Connect@8"
#endif

我很感激任何帮助。


您必须导出不带任何修饰的函数名称的选项(独立地根据您在 x86 中使用的特定调用约定,__stdcall, __cdecl,或其他)并与相同的未修饰名称在 x86 和 x64 版本中,是使用以下命令导出 DLL 函数DEF 文件 https://msdn.microsoft.com/en-us/library/d91k01sh.aspx.

例如。您可以将这样的 .DEF 文件添加到您的项目中:

LIBRARY YOURDLL
EXPORTS
   Connect          @1
   AnotherFunction  @2
   ... etc. ...   

重现跟随

在 Visual Studio 中创建一个空的解决方案(我使用的是 VS2013),并在其中创建一个空的 Win32 控制台项目(测试客户端)和一个空的 Win32 DLL 项目(test DLL).

添加这个NativeDll.def .DEF 文件 in the DLL项目:

LIBRARY NATIVEDLL
EXPORTS
    SayHello @1

添加这个NativeDll.cppC++ 源代码位于DLL项目:

///////////////////////////////////////////////////////////////////////////////
// 
// NativeDll.cpp    -- DLL Implementation Code
//
///////////////////////////////////////////////////////////////////////////////


#include <Windows.h>
#include <atldef.h>
#include <atlstr.h>


//
// Test function exported from the DLL
// 
extern "C" HRESULT WINAPI SayHello(PCWSTR name)
{
    //
    // Check for null input string pointer
    //
    if (name == nullptr)
    {
        return E_POINTER;
    }

    try
    {
        //
        // Build a greeting message and show it in a message box
        //
        CString message;
        message.Format(L"Hello %s from the native DLL!", name);        
        MessageBox(nullptr, message, L"Native DLL Test", MB_OK);

        // All right
        return S_OK;
    }
    //
    // Catch exceptions and convert them to HRESULT codes
    //
    catch (const CAtlException& ex)
    {
        return static_cast<HRESULT>(ex);
    }
    catch (...)
    {
        return E_FAIL;
    }
}

添加这个NativeClient.cppC++ 源代码位于客户测试项目:

///////////////////////////////////////////////////////////////////////////////
//
// NativeClient.cpp     -- EXE Test Client Code
//
///////////////////////////////////////////////////////////////////////////////


#include <Windows.h>


//
// Prototype of the function to be loaded from the DLL
//
typedef HRESULT (WINAPI *SayHelloFuncPtr)(PCWSTR /* name */);


//
// Simple RAII wrapper on LoadLibrary()/FreeLibrary().
//
class ScopedDll
{
public:

    //
    // Load the DLL
    //
    ScopedDll(PCWSTR dllFilename) throw()
        : m_hDll(LoadLibrary(dllFilename))
    {
    }


    //
    // Unload the DLL
    //
    ~ScopedDll() throw()
    {
        if (m_hDll)
        {
            FreeLibrary(m_hDll);
        }
    }


    //
    // Was the DLL loaded successfully?
    //
    explicit operator bool() const throw()
    {
        return (m_hDll != nullptr);
    }


    //
    // Get the DLL handle
    //
    HINSTANCE Get() const throw()
    {
        return m_hDll;
    }


    //
    // *** IMPLEMENTATION ***
    //
private:

    //
    // The wrapped raw DLL handle
    //
    HINSTANCE m_hDll;


    //
    // Ban copy
    //
private:
    ScopedDll(const ScopedDll&) = delete;
    ScopedDll& operator=(const ScopedDll&) = delete;
};


//
// Display an error message box
//
inline void ErrorMessage(PCWSTR errorMessage) throw()
{
    MessageBox(nullptr, errorMessage, L"*** ERROR ***", MB_OK | MB_ICONERROR);
}


//
// Test code calling the DLL function via LoadLibrary()/GetProcAddress()
//
int main()
{
    //
    // Return codes
    //
    static const int kExitOk = 0;
    static const int kExitError = 1;


    //
    // Load the DLL with LoadLibrary().
    // 
    // NOTE: FreeLibrary() automatically called thanks to RAII!
    //
    ScopedDll dll(L"NativeDll.dll");
    if (!dll)
    {
        ErrorMessage(L"Can't load the DLL.");
        return kExitError;
    }


    //
    // Use GetProcAddress() to access the DLL test function.
    // Note the *undecorated* "SayHello" function name!!
    //
    SayHelloFuncPtr pSayHello 
        = reinterpret_cast<SayHelloFuncPtr>(GetProcAddress(dll.Get(), 
                                                           "SayHello"));
    if (pSayHello == nullptr)
    {
        ErrorMessage(L"GetProcAddress() failed.");
        return kExitError;
    }


    //
    // Call the DLL test function
    //
    HRESULT hr = pSayHello(L"Connie");
    if (FAILED(hr))
    {
        ErrorMessage(L"DLL function call returned failure HRESULT.");
        return kExitError;
    }


    //
    // All right
    //
    return kExitOk;
}

构建整个解决方案(.EXE 和 .DLL)并运行本机 .EXE 客户端。
这是我在电脑上得到的:

有用不加修改并与未装饰的函数名称(只是SayHello) on bothx86 和 x64 版本.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

x64 DLL 导出函数名称 的相关文章

  • 如何在 c#.net 中将十进制转换为 ASCII?

    谁能帮助我如何使用 C net 将十进制转换为 ASCII 当我在文本框 1 中输入小数时 单击 转换 按钮后 结果将显示在文本框 2 中 我的问题是如何将十进制转换为 ASCII 的代码 这个怎么做 这是我在网上找到的一个简单的解决方案
  • C++11 中的延迟初始化顺序

    考虑以下代码 分为三个编译单元 a h struct A void Register const char s const char m s 10 int m i 0 A GetA a cpp include a h include
  • 如何管理 JSONP 响应中的 ' ?

    我需要像这样管理 char 在我的 JSONP 请求中 通过 jquery 使用 Ajax 所以 来自 C 这就是我所做的 myText Hello I m a string myText Replace Response Write Re
  • 空别名共享指针是否是无操作删除共享指针的良好替代方案?

    有时我需要shared ptr具有无操作删除器的实例 因为 API 期望shared ptr例如 它想要存储有限的时间 但我得到了一个原始指针 不允许我拥有比我运行的时间更长的时间 对于这种情况 我一直使用无操作删除器 例如 const v
  • 错误:LNK1120:5 个未解析的外部

    我试图在我的帖子中获取有关已安装应用程序的详细信息 而且 我收到以下错误 Code include
  • WPF PasswordBox 中的密码不可绑定的安全优势?

    我只是偶然发现一个事实PasswordWPF 的属性PasswordBoxes 不可绑定安全原因 这使得在 MVVM 上下文中使用它们相当麻烦 答案如https stackoverflow com a 1493330 3198247 htt
  • 为什么 C# 三元运算符不能与委托一起使用?

    当分支选择函数时 使用三元运算符来选择函数可能是有意义的 但这是不可能的 为什么 public class Demo protected bool branch protected void demo1 protected void dem
  • elmah定制提供商及暴露事件

    我想知道如何创建自定义提供程序来存储错误日志 例如 Windows 事件查看器的提供者 如果到目前为止不可能 我还想知道是否有任何可以覆盖的公开事件 以便我可以注入我的代码 获取异常 做任何我想做的事情 我知道 Global asax 中有
  • 使用迭代器与索引访问向量元素有什么区别?

    使用迭代器与索引访问向量元素有什么优点 为什么迭代器比索引更好 在索引不可用的情况下 例如 std list 对于 例子 在通用函数接受迭代器的情况下 叫做 编写应该使用的函数模板时 不止一种容器类型 他们的存在是为了创造均匀性在所有容器和
  • 将“列表”项附加到 StringBuilder

    我尝试将项目附加到List
  • 如何从源代码编译picoProlog?

    我是计算机科学专业的学生 正在学习 Prolog 逻辑编程 我发现了一个有趣的 Prolog 解释器 picoProlog http spivey oriel ox ac uk corner Logic Programming http s
  • C++ 流到内存

    我怎样才能创造std ostream and std istream对象指向我分配和管理的一块内存 我不希望流释放我的内存 我正在考虑使用rdbuf gt pubsetbuf 修改其他流之一 例如sstringstream 不过我认为str
  • C# 我可以访问没有完整限定名称的枚举吗

    我有一个 C 枚举类型 它以非常长的限定名称结尾 例如 DataSet1 ContactLogTypeValues ReminderToFollowupOverdueInvoice 为了便于阅读 如果我可以告诉一个特定的函数只使用名称的最后
  • 将 byte[] 作为文件打开,而不先将其实际保存为文件

    打开以 byte 形式存储在数据库中的 Word 文件的最佳方法是什么 我必须将一些文档存储在 Access 数据库中 Word 文件 2003 及更高版本 并存储在严格通过 CD 运行的应用程序上 不幸的是 它们必须位于数据库中 并且不能
  • “auto_ptr”和 STL 容器:编写错误用法的示例

    读完本教程后提出这个问题 http www cprogramming com tutorial auto ptr html http www cprogramming com tutorial auto ptr html 在那里你可以找到以
  • 通过构建服务器进行 Nuget 恢复“无法找到版本”

    我有一个 VS 解决方案 作为 TeamCity Build 的一部分 我们从私有 NuGet feed myget 和公共 feed nuget org 恢复包 大多数软件包都可以正常恢复 但它会挂在下面的 WebApi 和 Mono S
  • DllImport 名称不完整

    我在 NET 下使用多个 P Invoke 但是 我希望我的库能够在 Windows 和 Linux 上运行 最好使用相同的二进制文件 由于我所依赖的本机库可在多个平台上使用 因此我希望将它们与我的托管库的二进制文件一起使用 现在我正在使用
  • 如何在调试 C 程序时将 gdb 值转换为 python 数字对象

    我在调试 C 程序时使用 python2 6 的 gdb 模块 并希望根据实例的 Type 将 gdb Value 实例转换为 python 数字对象 变量 例如 把我的C程序SomeStruct gt some float val 1 6
  • 如何为 Office AddIn 创建静默安装程序

    我在为使用 C 中的 VSTO 开发的 Outlook 加载项创建静默安装程序时遇到问题 安装程序是由 clickOnce 生成的 Outlookaddin vsto 此加载项将由 SCCM 在多台计算机上发布 我需要静默安装 但当软件包到
  • 如何在 WPF 数据网格中显示相关表中的数据

    我只是在寻找使用 WPF Datagrid Linq 的方法 并且试图找出如何显示数据网格中相关表中的数据 例如我有3张表 客户 id 姓名 产品 id 名称 订单 id 客户 ID 产品 ID 我已经在数据库表中建立了关系 我已将表添加为

随机推荐

  • 使用 GitLab CI 在本地运行测试?

    如果在 GitLab CI 上配置了 GitLab 项目 是否有办法在本地运行构建 我不想将我的笔记本电脑变成构建 运行者 我只是想利用 Docker 和 gitlab ci yml在本地运行测试 即全部预先配置 这样做的另一个优点是我确信
  • 获取Java InputStream后面的文件的字节数

    正如标题所示 我需要知道文件在输入流 后面 有多少字节 我不想下载所有字节和计数 需要很长时间 我只需要知道文件有多少字节 像这样 int numberOfBytes countBytes inputStream 所以 我需要 countB
  • Haskell - 计算列表中每个不同元素出现的次数

    我是 Haskell 的新手 只是想编写一个列表理解来计算列表中每个不同值的频率 但我在最后一部分遇到了麻烦 到目前为止我有这个 frequency Eq a gt a gt Int a frequency list count y lis
  • 如何使用 css3 动画将宽度和高度设置为 100%?

    我有以下代码 HTML div div css div background tomato width 100px height 100px webkit animation animateThis 0 3s ease in webkit
  • 无法远程连接JMX?

    由于某些奇怪的原因 我无法使用VisualVM or jconsole到 JMX 用于启动要监控的VM的参数 Dcom sun management jmxremote Dcom sun management jmxremote authe
  • 默认情况下,所有 Google Chrome 扩展程序都是开源的吗?

    我想知道如果我编写了 Google Chrome 扩展程序 任何人都可以使用我的代码吗 看起来人们将能够看到您的代码 如果他们可以看到您的代码 他们就有可能使用它 视窗 C Documents and Settings USERNAME L
  • 如何在 PL/SQL 中解析逗号分隔的字符串? [复制]

    这个问题在这里已经有答案了 我在 PL SQL 脚本中有一个逗号分隔的字符串 例如 data a b c d e 我需要在脚本中解析它 我想循环遍历字符串并处理每个项目 就像 foreach 循环一样 这在 PL SQL 中可能吗 有人可以
  • 如何从一个活动组中的活动导航到android中的另一个活动

    我有两个标签 在这两个选项卡中我有不同的活动组 如何从一个活动组中的一个活动导航到android中的另一个活动 请帮我举出合适的例子 就我而言 我确实喜欢这样 当我单击父组最后一个活动中的完成 提交按钮时 我提交了值 将值存储到服务器 数据
  • 在 PHP 中格式化 JSON 格式的文本文件

    所以我得到了一个带有按钮的 HTML 页面 当我单击该按钮时 一个单独的 javascript 文件会向我的 PHP 文件发送 GET 请求 并期望返回 JSON 对象 我的 PHP 读取 JSON 格式的文本文件 并将其转换为 JSONO
  • ASP.NET身份更改密码

    我需要能够由管理员更改用户密码 因此 管理员不应输入用户的当前密码 他应该能够设置新密码 我查看了 ChangePasswordAsync 方法 但该方法需要输入旧密码 因此 此方法不适合此任务 因此我通过以下方式做到了 HttpPost
  • 在 App Store 上发布应用程序后,iAd 未在设备上显示

    检查了有关在 App Store 上发布应用程序后不显示 iAd 的几个问题 对 iAd 进行所有必要的设置 测试广告在模拟器和设备中显示良好 然后发布应用程序并为该应用程序启用 iAd 网络 在iAd Network部分 状态显示为 Li
  • Xcode 4:如何更改 ${EXECUTABLE_NAME} 变量的值?

    我想找到 xcode 4 2 中定义的 EXECUTABLE NAME 全局变量在哪里 您的目标 gt 构建设置 gt 产品名称
  • RSpec 中“it”关键字的作用是什么?

    我正在关注rails3tutorial 在进行如下测试时 我不明白 it 关键字的含义 require spec helper describe UsersController do render views describe GET ne
  • 在android中绘制单点触摸运动路径

    我正在尝试制作一个绘图应用程序 我想要绘制单点触摸运动路径在 android 中 就像 Swype 键盘的方式一样 因此我想存储每个像素的 x y 坐标将运动路径转化为数据结构 我如何使用 MotionEvent 指针来执行此操作 您可能不
  • 使用自定义源增强 Iostreams zlib_error

    我正在尝试使用zlib decompressor通过一个解压缩数据istreambuf iterator 我找不到使用输入迭代器作为流的输入的内置方法 如果已经存在 请指出一种方法 所以我写了这个源代码 template
  • JDK:如何以编程方式启用 PlatformLogger

    我需要以编程方式启用某些 JDK7 内部类的日志记录 这就是我在应用程序初始化时所做的事情 httpLogger Logger getLogger sun net www protocol http HttpURLConnection ht
  • SFINAE 在返回类型中工作,但不作为模板参数[重复]

    这个问题在这里已经有答案了 我已经使用过 SFINAE 习语很多次了 而且我习惯了把我的std enable if lt gt 在模板参数中而不是在返回类型中 然而 我遇到了一些微不足道的情况 它不起作用 我不知道为什么 首先 这是我的主要
  • 如何在wpf datagrid中显示数据集的相关数据

    我有一个包含两个表的数据集 存在简单的一对多父子关系 例如 Parent Table ParentId int Name string Child Table ChildId int ParentId int Name string 在此数
  • 异步方法调用和模拟

    为什么模拟用户上下文仅在异步方法调用之前可用 我编写了一些代码 实际上基于 Web API 来检查模拟用户上下文的行为 async Task
  • x64 DLL 导出函数名称

    我正在尝试将 32 位 dll 和应用程序 移植到 64 位 并且我成功地构建了它而没有错误 当尝试使用我的 64 位应用程序加载它时 我注意到导出的函数名称不同 这就是我导出函数的方式 ifdef cplusplus extern C e