使用extern C改善显式调用dll

extern "C"的简单解析         我们前面介绍了显式调用dll的方法,例如


http://www.cnblogs.com/laogao/archive/2012/12/07/2806528.html ,其中在GetProcAddress第二个参数的填写煞费苦心,我们需要比较麻烦地使用vs自带的dumpbin查看dll的具体函数,即使后来可以使用MAKEINTRESOURCE直接填写函数序号来不直接填写函数名,依然你需要在dumpbin中查找函数的序号,比较费力。

         其实我们有更好的方法来解决这个问题,其中一个比较好的一个方法是改用extern "C"来修饰函数,使之按照c的风格来编译函数。我们知道c不支持函数重载,因此我们定义的时候用的什么名字,在显式调用dll的时候也是用的这个名字,完全不用改变,很简单。

        在进行下面的介绍之前,先可以阅读这个文章《extern "C"的简单解析》

        下面我们介绍两个例子。

例1. 在纯C++环境下使用c语言方式编译dll,然后调用

      CreateDLL.h

<span style="color:#000000;">// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 CREATEDLL_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// CREATEDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef CREATEDLL_EXPORTS
#define CREATEDLL_API __declspec(dllexport)
#else
#define CREATEDLL_API __declspec(dllimport)
#endif#ifdef __cplusplus
extern "C"
{
#endifCREATEDLL_API void printMax(int&, int&);
#ifdef __cplusplus
}
#endif // __cplusplus
</span>
// CreateDLL.cpp : 定义 DLL 应用程序的导出函数。
//#include "stdafx.h"
#include "CreateDLL.h"
#include <iostream>CREATEDLL_API void printMax(int& a, int& b)
{std::cout << "Among (" << a << "," << b << "), the Max Number is " << (a > b ? a : b) << "\n";
}

然后点击“生成”,即可生成dll和lib。接下来我们就可以直接使用了。注意:生成dll的时候,需要先设置dll的项目为启动项。当使用dll的时候,需设置使用dll的项目为启动项。

先看显式调用:

#include <Windows.h>
#include <iostream>typedef void(*FUNA)(int&, int&);int main()
{const char* dllName = "CreateDLL.dll";int x(100), y(100);HMODULE hDLL = LoadLibrary(dllName);if (hDLL!=NULL){FUNA fp1 = FUNA(GetProcAddress(hDLL, "printMax"));if (fp1!=NULL){std::cout << "Input 2 Numbers:";std::cin >> x >> y;fp1(x, y);}else{std::cout << "connot find the function "<<"printMax" << std::endl;}FreeLibrary(hDLL);}else{std::cout << "cannot load dll"<<dllName << std::endl;}system("pause");return 0;}

注意观察,我们的GetProcAddress的第二个参数直接使用原来的函数名。另外需要注意的是在使用dll的项目中,我们没有包含dll的头文件,但是仍然可以使用。但是有时候也过不去,此时你需要包含dll的.h的路径。

再看隐式调用

#include "CreateDLL.h"
#include <iostream>
using namespace std;#pragma  comment(lib,"CreateDLL.lib")int main()
{int a,b;cout << "input 2 num:";cin >> a >> b;printMax(a,b);system("pause");return 0;
}

将.h,.lib,.dll一块儿放在项目目录下,然后在程序中使用#pragma comment(lib,"CreateDLL.lib"),即可成功链接dll。与显式调用,隐式调用比较简单。

另外在上一篇《c++显式加载dll并使用DLL的类》 ,我们也使用了extern "C"的风格

extern "C" INTERFACE_API Interface* Export(void); 

例2. 在纯C环境下使用c语言方式编译dll,然后在C++中调用
    
CreateDLL.h

//c.h
#ifndef _C_H_
#define _C_H_   //防止被重复包含#ifdef CREATEDLL_EXPORTS
#define CREATEDLL_API __declspec(dllexport)
#else
#define  CREATEDLL_API __declspec(dllimport)
#endif#ifdef __cplusplus
extern "C" {
#endifextern  CREATEDLL_API int add(int x, int y);#ifdef __cplusplus
}
#endif#endif

CreateDLL.c

#include "CreateDLL.h"
int add(int x, int y)
{return x + y;
}

然后我们就可以生成dll了。注意我们这里都是c语言。

然后我们在c++中调用dll。

显式调用:

#include <Windows.h>
#include <iostream>
#include "CreateDLL.h"typedef int(*Func)(int, int);#pragma  comment(lib,"CreateDLL.lib")int main()
{HMODULE Hdll = LoadLibrary("CreateDLL.dll");if (Hdll!=nullptr){Func f = Func(GetProcAddress(Hdll, "add"));if (f!=nullptr){std::cout << "input 2 num:";int a, b;std::cin >> a >> b;std::cout << "result is " << add(a, b);}else{std::cout << "connot find the function " << "add" << std::endl;}FreeLibrary(Hdll);}else{std::cout << "cannot load dll" << "CreateDLL.dll" << std::endl;}system("pause");return 0;
}

注意要将CreateDLL.h和CreateDLL.lib放在项目目录下。

隐式调用:

#include "CreateDLL.h"
#include <iostream>
using namespace std;#pragma  comment(lib,"CreateDLL.lib")int main()
{int a,b;cout << "input 2 num:";cin >> a >> b;cout<<"result is "<<add(a,b);system("pause");return 0;
}

解读:

文件为*.c,__cplusplus没有被定义,extern "C" {}这时没有生效,对于C语言只是extern int add(int, int);而编译c++源文件,__cplusplus被定义,对于C++他看到的是extern "C" {extern int add(int, int);},编译器就会知道add(1, 0)调用的是C连接。 
很多DLL的生成文件(XXX.c)中常出现extern "C" ,windows采用C语言编译创建dll,C程序可以正确调用DLL,而当用户使用C++调用DLL时,extern "C" {}就起作用了。

附录:

1.例1

2.例2




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258977.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《移动App测试的22条军规》—App测试综合案例分析23.13节测试微信App的流量和电量消耗...

本节书摘来自异步社区《移动App测试的22条军规》一书中的App测试综合案例分析&#xff0c;第23.13节测试微信App的流量和电量消耗&#xff0c;作者黄勇&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。 23.13 测试微信App的流量和电量消耗关于微信App消耗流…

UVA 10269 Super Mario,最短路+动态规划

这个题目我昨晚看到的&#xff0c;没什么思路&#xff0c;因为马里奥有boot加速器&#xff0c;只要中间没有城堡&#xff0c;即可不耗时间和脚力&#xff0c;瞬间移动不超过L距离&#xff0c;遇见城堡就要停下来&#xff0c;当然不能该使用超过K次。。。我纠结了很久&#xff0…

python做数据可视化的代码_Python数据可视化正态分布简单分析及实现代码

Python说来简单也简单&#xff0c;但是也不简单&#xff0c;尤其是再跟高数结合起来的时候。。。 正态分布&#xff08;Normaldistribution&#xff09;&#xff0c;也称“常态分布”&#xff0c;又名高斯分布&#xff08;Gaussiandistribution&#xff09;&#xff0c;最早由A…

ACdream 1061(abs用法)

题目链接&#xff1a;http://acdream.info/problem?pid1061 主要是abs用法&#xff0c;看题目的数据 long long的最大值&#xff1a;9223372036854775807 long long的最小值&#xff1a;-9223372036854775808 unsigned long long的最大值&#xff1a;18446744073709551615 由题…

wpf window 不执行show 就不能load执行_Numpy反序列化命令执行漏洞分析(CVE-2019-6446)附0day...

1、介绍 NumPy 是 Python 机器学习库中之一&#xff0c;主要对于多为数组执行计算。NumPy 提供大量的 函数和操作&#xff0c;能够帮助程序员便利进行数值计算。在 NumPy 1.16.0 版本之前存在反序列化 命令执行漏洞&#xff0c;用户加载恶意的数据源造成命令执行。2、环境 软件…

使用Def文件导出dll

前面我们介绍了dll的生成&#xff0c;大多数是使用extern "C"__declspec(dllexport)函数名的方法导出dll。其实我们还有另一种方法来导出dll。 先介绍参考文献&#xff1a; 1.dll导出声明相关 2.VS2012中 C创建DLL图解 3.DLL中导出函数的两种方式(dllexport与.…

HDU 1003 Maxsum

题目大意&#xff1a;求出数列的最大子段和&#xff0c;并且说明是从第几项至第几项。 题解1&#xff1a;简单贪心。 #include <cstdio> #define rep(i,n) for(int i1;i<n;i) int main(){int t,l0;scanf("%d",&t);while(t--&&l){if(l!1)printf…

《JavaScript面向对象精要》——1.8 原始封装类型

本节书摘来自异步社区《JavaScript面向对象精要》一书中的第1章&#xff0c;第1.8节&#xff0c;作者&#xff1a;【美】Nicholas C. Zakas著&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 1.8 原始封装类型 JavaScript中一个最让人困惑的部分可能就是原始…

XML语法学习

本文章集合两篇博文而写&#xff0c;两篇博文地址&#xff1a; XML学习总结(二)——XML入门&#xff1a; XML基础<第一篇> XML简介 XML是一种标记语言&#xff0c;用于描述数据&#xff0c;它提供一种标准化的方式来来表示文本数据。XML文档以.xml为后缀。需要彻底注…

FM实现F4帮助系列三:弹出框多筛选…

FM实现F4帮助系列三&#xff1a;弹出框多筛选条件的搜索帮助&#xff08;根据搜索帮助筛选字段&#xff09;函数&#xff1a;F4IF_GET_SHLP_DESCRF4IF_START_VALUE_REQUEST效果图&#xff1a;本例子代码&#xff1a;找到需要的帮助:*&------------------------------------…

[数分提高]2014-2015-2第9教学周第1次课 (2015-04-28)

设 $$\bex a,b>0,\quad 0\leq f\in \calR[a,b],\quad \int_a^b xf(x)\rd x0. \eex$$ 试证: $$\bex \int_a^b x^2f(x)\rd x\leq ab \int_a^b f(x)\rd x; \eex$$ 并给出使得下列不等式成立的 (您认为的) 最优数: $$\bex \int_a^b x^3f(x)\rd x\leq (\quad) \int_a^b f(x)\rd x…

《计算复杂性:现代方法》——0.2 判定问题/语言

本节书摘来自华章计算机《计算复杂性&#xff1a;现代方法》一书中的第0章&#xff0c;第0.2节&#xff0c;作者 &#xff3b;美&#xff3d;桑杰夫阿罗拉&#xff08;Sanjeev Arora&#xff09;&#xff0c;博阿兹巴拉克&#xff08;Boaz Barak&#xff09;&#xff0c;译 骆吉…

python从date目录导入数据集_使用python划分数据集

无论是训练机器学习或是深度学习&#xff0c;第一步当然是先划分数据集啦&#xff0c;今天小白整理了一些划分数据集的方法&#xff0c;希望大佬们多多指教啊&#xff0c;嘻嘻~ 首先看一下数据集的样子&#xff0c;flower_data文件夹下有四个文件夹&#xff0c;每个文件夹表示一…

开源牛人 zcbenz

事情是这样的&#xff0c;微软推出了Visual Studio Code&#xff0c;我很好奇他怎么做跨平台的&#xff0c;所以就找找资料&#xff0c;在他的网站中是这么描述的&#xff1a; Architecturally, Visual Studio Code combines the best of web, native, and language-specific t…

eclipse 与 tomcat 的那些路径

我们用mvn创建了一个web工程&#xff0c;同时希望在eclipse里调试开发。mvn有mvn的路径要求&#xff0c;eclispe有eclipse的默认路径&#xff0c;怎么整合二者&#xff1f; 首先介绍一下eclipse的默认路径。 重点在Server Locations里面。 下面我们把[workspace]/.metadata\.pl…

boost解析xml文件

前面我们介绍了xml文件&#xff0c;今天我们试着用boost库来解析xml文件。我们将举两个例子来说明怎么使用。 来自boost官方的例子 先看xml文件的内容&#xff1a; <debug><filename>debug.log</filename><modules><module>Finance</modul…

使用网桥模式(bridge networking mode)配置KVM-QUME虚拟机网络

&#xff08;1&#xff09;linux要工作在网桥模式&#xff0c;所以必须安装两个RPM包。即&#xff1a;bridge-utils和tunctl。它们提供所需的brctl、tunctl命令行工具。能够使用yum在线安装&#xff1a; [rootserver3 ~]# yum install bridge-utils &#xff08;2&#xff09;查…

python数据处理常用函数_pandas数据分析常用函数总结大全:上篇

基础知识在数据分析中就像是九阳神功&#xff0c;熟练的掌握&#xff0c;加以运用&#xff0c;就可以练就深厚的内力&#xff0c;成为绝顶高手自然不在话下&#xff01; 为了更好地学习数据分析&#xff0c;我对于数据分析中pandas这一模块里面常用的函数进行了总结。整篇总结&…

XML的应用

1.XML的定义: XML 于 1998 年 2 月 10 日成为 W3C 的推荐标准。xml一般指可扩展标记语言&#xff0c;可扩展标记语言是一种很像超文本标记语言的标记语言。它的设计宗旨是传输数据&#xff0c;而不是显示数据。 2.通过XML我们可以自定义自己的标签&#xff0c;如&#xff1a; &…

虚拟机VMware里 windows server 2003 扩充C盘方法

你会经常用windows server 2003 吗&#xff1f;应该不会吧&#xff0c;有时一些东西必须装在windows server 2003 上才能用&#xff0c;所以 用虚拟机把&#xff0c;好&#xff0c;装在虚拟机上&#xff0c;8G的C盘够你用吗&#xff0c;一个稍微大点的软件就可能就没空间来存储…