GetProcAddress()函数动态调用DLL中的函数,是否必须通过extern C声明导出函数?

通过GetProcAddress函数动态调用dll中的函数,是否必须通过extern "C"声明导出函数?

如题,网上搜了N多资料,一直找不到确定的答案,目前答案是“是”。

很多资料上都只是说明“如果没有 extern "C"修饰,输出函数仅仅能从 C++ 代码中调用”,却并没有明确这个调用是通过显式调用还是隐式调用,我也一直没有看到过有代码是通过显示调用没有 extern "C" 修饰的导出函数。

MSDN上也只是说:

The spelling and case of the function name pointed to by lpProcName must be  identical to that in the EXPORTS statement of the source DLL's module-definition (.DEF) file. The exported names of Win32 API functions may differ from the names you use when calling these functions in your code.

下面再从理论方面进行一些分析:

GetProcAddress函数声明是:

FARPROC GetProcAddress(

HMODULE hModule,   // handle to DLL module

LPCSTR lpProcName   // name of function

);

C++是支持函数重载的,也就是说允许多个不同的函数可以有同样的函数名,如果不通过extern "C"修饰,就可以输出相同的函数名。这样,就和GetProcAddress函数声明不一致了,所以推断不能动态调用没有extern "C"修饰的导出函数,因为GetProcAddress函数是通过函数名来唯一确定被调用函数的地址的。

1个回答

显示调用必须使用extern "C"修饰符。隐式调用可以使用任何类型,但只有C++能调用没有extern "C"修饰的导出函数。GetProcAddress是一种通用的获取函数入口点的API,能被任何语言调用,所以限制一定比较多,比如它的参数一定是一个ANSI串(操作系统并未提供UNICODE版本)。

2个回答

GetProcAddress实际上跟直接调用myfunc()一样,都是查询Export表来得到函数地址再去调用,因此修饰符不对就会造成找不到entry,是不行的。

3个回答

C函数和C++函数的名称是不一样的,可以使用工具来查看,比如Dependency Walker。如果想试验,可以根据工具看到的名称来调用GetProcAddress试试。

4个回答

有两种例外情况可以不加extern "C":

1. 如果不是用C++编译器而是用C编译DLL,名字不会变,可以不加extern "C";

2. 如果DLL的使用者知道是用C++编译器编译DLL,不加extern "C"也可以,因为他知道名字改变的规则。调用GetProcAddress,把函数名字改了就是了。

5个回答

C++编译器和C编译器编译后生成的函数名不一样。GetProcAddress认为是cdecl的函数,而编译DLL的是VC++,所以要加一个extern "C"的修饰符指明以cdecl的方式生成函数。

6个回答

发现不用加extern "C"也是可以的,只要在调用端用修饰过的函数名即可,不能用原函数名。

例子关键代码如下:

DLL部分:

// This is an example of an exported function.

DLL1_API int __cdecl fnDll1(void)

{

return 42;

}

输出的修饰函数名为?fnDll1@@YAHXZ

DLL1_API int __cdecl fnDll1(int a)

{

return 42+a;

}

输出的修饰函数名为?fnDll1@@YAHH@Z

-----------------------------

EXE部分:

HINSTANCE hModule = LoadLibrary("dll1.dll");

ASSERT(hModule);

typedef int (*fnDll1)();

fnDll1 pfnDll1 = NULL;

//VERIFY(pfnDll1 = (fnDll1)::GetProcAddress(hModule, "fnDll1"));

VERIFY(pfnDll1 = (fnDll1)::GetProcAddress(hModule, "?fnDll1@@YAHXZ"));

ASSERT(pfnDll1() == 42);

typedef int (*fnDll2)(int);

fnDll2 pfnDll2 = NULL;

VERIFY(pfnDll2 = (fnDll2)::GetProcAddress(hModule, "?fnDll1@@YAHH@Z"));

ASSERT(pfnDll2(3) == 45);

---------------------------

这事暂时可以告一段落了,实验还是最有力的证明。

GetProcAddress()函数动态调用DLL中的函数,是否必须通过extern C声明导出函数?相关推荐

  1. 通过GetProcAddress函数动态调用dll中地函数,是否必须通过extern C声明导出函数?(转)...

    通过GetProcAddress函数动态调用dll中的函数,是否必须通过extern "C"声明导出函数? [已结贴,结贴人:darongtou] 如题,网上搜了N多资料,一直找不 ...

  2. Qt调用dll中的功能函数

    http://www.cnblogs.com/hicjiajia/archive/2010/08/27/1810239.html 声明: 事先我已经自己动手写了一个简单的dll文件(myDLL.dll ...

  3. 【转】Qt调用dll中的功能函数

    DLL 优点 ------------------------------------- 1.扩展了应用程序的特性: 2.可以用许多种编程语言来编写: 3.简化了软件项目的管理: 4.有助于节省内存: ...

  4. python如何调用dll库中的函数_Python调用dll库接口-ctypes方法

    背景 最近需要用python写个脚本程序(win10 环境),需要调用现成的dll库完成这项任务,对于一直在Linux平台上开发程序的本人来说,从没有过使用dll的经历(不得不说还是so大法好),遇到 ...

  5. C#程序实现动态调用DLL的研究(转)

    摘 要:在<csdn开发高手>2004年第03期中的<化功大法--将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...

  6. 如何调用 DLL 中的函数

     如何调用 DLL 中的函数 在 DLL工程中的 cpp中函数定义如下: extern "C" _declspec (dllexport ) int add(int a, ch ...

  7. 如何调用DLL中的函数

    如何调用 DLL 中的函数 在 DLL工程中的 cpp中函数定义如下: extern "C" _declspec (dllexport ) int add(int a, char ...

  8. 天马行空W:在C++中调用DLL中的函数

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

  9. 在C++中调用DLL中的函数

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

最新文章

  1. [转[c++]从int转换成string
  2. Android 修改手机hosts域名 (绑定host域名 )
  3. Tensorflow 2.3 GPU安装
  4. WPF纯手工两步打造图片切割工具(一)
  5. 8个超好用的Python内置函数,提升效率必备!
  6. ajax是操作系统吗,ajax 跟post 可以设置它是否同步执行
  7. 【JavaScript】用Switch实现成绩等级判断
  8. java 原子数据类型_java并发编程(十一)----(JUC原子类)基本类型介绍
  9. 创建Win2003域和Win2008域之间的信任关系,Active Directory系列之十八
  10. [转]深入理解C/C++ [Deep C (and C++)]
  11. 静态代理和动态代理的区别
  12. 数格子算面积的方法_数格子估算面积与数格点估算面积
  13. Flink 与 Storm的对比
  14. 解决卸载wifi共享软件后无法连网的问题
  15. 步进电机基础(2.6)-直线步进电机
  16. 人工智能发展到GPT4经历了什么,从专家系统到机器学习再到深度学习,从大模型到现在的GPT4
  17. 网络类型 ---- PAP认证配置 ---- CHAP认证----隧道技术
  18. 【个人项目整理】机器人、三维模型
  19. Jmeter之CSV文件相对路径、绝对路径
  20. faster rcnn源码解析

热门文章

  1. CentOS 7 使用yum安装出现错误
  2. Android各种dialog
  3. String当中的高效函数(优化)
  4. Sizeof的计算看内存分配
  5. Hadoop-2.2.0中文文档——MapReduce 下一代 -——集群配置
  6. [转]影响Cache的几个HTTP头信息
  7. Smartisan OS ROM 小米手机 2/2S 标准版 刷机教程
  8. 数据库表迁移到阿里云的方法有哪些
  9. Vant - 高效的 Vue 组件库,再造一个有赞移动商城也不在话下
  10. sharepoint2013的审核日志的时间区域设置