下VS2012生成DLL文件(1)

一:生成DLL

1:创建DLL工程

      文件->新建->项目->visual
c++->win32->win32控制台应用程序(win32型为可)

      填写项目名称MyDLL->确定->下一致步->DLL(附加选项
对空项目打钩)->完成。

      到这边DLL工程就算创办了了,下面新建六只文本MyDLL.cpp和MyDLL.h。

      MyDLL.cpp内容如下:

C语言 1

1 #include  

2 using namespace std;

3 #include “MyDLL.h”

4    

5 int Add(int &a,int &b)

6 { 

7     return a+b;    

8 }

    

 

 MyDLL.h内容如下:  

1 #pragma once 

2  

C语言,3 extern “C” __declspec(dllexport) 

int Add(int &a,int &b); 

点击生成Bulid –>Bulid
MyDLL,dll文件就万分成了,vs2008无克直接生成lib文件,那个时段便用我们在起dll工程的下
再新建一个def文件,默认生成然后又生得能够抱lib文件了,但好经过

改工程属性里面的general->project default->configure
type修改为lib,就能够生成lib文件。

留意:假设当既是的工达标创立dll或者lib,不需要修改工程,只要将工程属性之中的general->project
default->configure
type修改为lib或者dll,就好生成lib文件要dll文件了

于C++程序中动用刚才生成的DLL文件步骤:

新建一个win32
控制台工程,取名testMyDLL,新建两独公文:testMyDLL.cpp和testMyDLL.h,

首先要 隐式链接使静态加载的办法,相比简单,需要.h、.lib、.dll三件套。新建“控制台应用程序”或“空项目”。配置如下:(这同样碰好紧要)

 项目->属性->配置属性->VC++ 目录->
在“包含目录”里补充加头文件MyDLL.h所在的目录 

花色->属性->配置属性->VC++ 目录->
在“库目录”里上加头文件MyDLL.lib所当的目 
项目->属性->配置属性->链接器->输入->
在“附加依赖项”里充分“MyDLL.lib”(若有差不七个 lib 则盖空格隔开)

testMyDLL.cpp内容如下:

#include “testMyDLL.h” 

#pragma comment(lib,”..\\debug\\MyDLL.lib”)//可以写成相对路径,不过路径一定如果因而\\来指明,即:J:\\Pr//ograms\\C++\\Practice\\DLLTEST\\DLLtest\\Debug\\MyDLL.lib”

#include  

using namespace std;

int main() 

{      

  int a =3;      

  int b =2;      

  cout<<Add(a,b)<<endl;        

  getchar();   

}  

testMyDLL.h内容如下:

 

#pragma once 

extern “C” _declspec(dllexport) int Add(int &a,int &b); 

 

 现在足编译通过了,然而程序运行就报错,还待用MyDLL.dll复制到即档变更的可执行文件所当的目。(这同接触老首要)

 这里用小心testMyDLL.cpp文件中调用lib的顿时词话:

 #pragma comment(lib,”..\\debug\\MyDLL.lib”) 

这里要指明lib所当的公文夹,当然大家吧足以在生成dll的MyDLL工程中,指定lib和dll文件之出口路径,直接到testMyDLL工程下。

 注意:倘使只有dll文件,那么得以先后中调用LoadLibrary()函数才会运用,假诺暴发lib文件,那么有些许栽办法可就展开调用

 

(1). Dependencies (推荐以,要求爆发lib源代码)

   一个列被分成三个工来做,一个主工程exe,其他为静态库lib

    Project–>dependencies,设置主工程的看重性也其他静态库lib

    这时,主工程的Resource Files中机动添加了lib

    在主工程中需要为此到其他库底地方在库底峰文件

(2). 直接以lib添加到要用之工中(不太推荐,lib没会集合管理)

    提供了lib和其头文件

    选拔工程–>右键–>Add Files to Project

    这时,主工程的Resource Files中机动添加了lib

    在主工程中需由此到其余库的职在库底腔文件

(3).  通过工程的Link设置(推荐,lib可以统一保管)

     提供了lib和其头文件

     Project–>settings–>Link,选择Categery中的Input

     在object/library modules里输入的动态链接库对应之.lib文件称

     在Additional library path中输入动态链接库对应之.lib的门径

     在主工程中需要为此到其他库底地方在库底条文件

(4).  #pragma (lib, “filename.lilb”)(不太推荐,lib没能统一管理)

      提供了lib和其头文件

      在主工程中待为此到其他库的地点在#pragma (lib, “filename.lilb”)

      在主工程中得因而到外库的职务在库底腔文件:

 

 =============================================================================================

extern C的使用

 C++是平种面向对象的顺序设计语言,为了援助函数的重载,C++对全局函数的处理情势与C有举世瞩目标例外,

题材: 为何标准头文件都暴发类似以下的社团?

 

#ifndef __INCvxWorksh 

#define __INCvxWorksh  

#ifdef __cplusplus 

extern “C” 

{

  #endif  /*…*/   

  #ifdef __cplusplus 

}  

#endif   

#endif /* __INCvxWorksh */ 

 

 分析:

肯定,头文件被的编译宏#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif的成效是防范该头文件于再引用。那么

#ifdef __cplusplus

extern “C” 

{

  #endif 

  #ifdef __cplusplus

}

#endif

 的意图同时是什么啊?我们拿当下文一一道来。

 1、extern “C”
包含重复意义,从字面上即可获取:首先,被它们修饰的目标是“extern”的;

副,被它们修饰的目的是“C”的。让大家来详细解读这简单再一次意思。

 被extern
“C”限定的函数或变量是extern类型的,extern是C/C++语言中注脚函数和全局变量效率范围(可见性)的首要字,该要字告诉编译器,其阐明的函数和变量可以当照模块或另模块中采纳。记住,下列语句:

extern int a;

 仅仅是一个变量的宣示,其并无是于概念变量a,并未为a分配内存空间。变量a在拥有模块中作同一种植全局变量只可以吃定义一涂鸦,否则会并发连续错误。平常,在模块的腔文件中针对依据模块提供给旁模块引用的函数和全局变量以重大字extern注脚,例如:

如果模块B欲引用该模块A中定义的全局变量和函数时只待蕴涵模块A的腔文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B尽管搜索不至该函数,不过并无汇合报错;它会以连日来路遭逢打模块A编译生成的目的代码中找到这函数。

 与extern对应的首要字是static,被它们修饰的全局变量和函数只好在本模块被动用。由此,一个函数或变量只恐为以模块使用时,其未容许被extern
“C”修饰。

 被extern “C”修饰的变量和函数是依据C语言格局编译和连续的;

 2、不加extern “C”注明时之编译情势

 首先看望C++中对类似C的函数是怎编译的。

 例如,要是有函数的原型为:

 1 void foo( int x, int y );

 该函数被C编译器编译后在符号库中之名字为_foo,而C++编译器则会发出像_foo_int_int之类的名(不同的编译器可能大成的名字不同,可是都接纳了一样的体制,生成的初名字称为“mangled
name”),_foo_int_int这样的讳包含了函数叫作、函数参数数量与类型音讯,C++就是凭这种体制来兑现函数重载的。

以C++中,函数void foo( int x, int y )与void foo( int x, float y
)编译生成的记是匪均等之,后者也_foo_int_float。

 同样地,C++中的变量除扶助有变量外,还协助类成员变量和全局变量。用户所编写程序的类成员变量可能跟全局变量同名,大家因为”.”来区分。而实质上,编译器在进展编译时,与函数的拍卖一般,也为接近中之变量取了一个无比的名,这一个名字和用户程序中同名的全局变量名字不同。

 3、未加extern “C”宣示时之接连格局

 假一旦于C++中,模块A的峰文件如下:

 // 模块A头文件 moduleA.h

#ifndef MODULE_A_H

#define MODULE_A_H

int foo( int x, int y );

#endif

 在模块B中引用该函数:

 #include “moduleA.h”

foo(2,3);

 实际上,在连接等,连接器会从模块A生成的对象文件moduleA.obj中摸索_foo_int_int这样的符号!

 4、加extern “C”扬言后的编译和连续形式

 加extern “C”注明后,模块A的腔文件化:

 // 模块A头文件 moduleA.h

#ifndef MODULE_A_H

#define MODULE_A_H

extern “C” int foo( int x, int y );

#endif

 在模块B的落实公文被仍然调用foo( 2,3 ),其结果是:

(1)模块A编译生成foo的对象代码时,没有针对性那些名字举行万分规处理,选拔了C语言的方法;

 

(2)连接器在啊模块B的对象代码寻找foo(2,3)调用时,寻找的凡未经修改的号子名_foo。

  假设当模块A中函数申明了foo为extern “C”类型,而模块B中涵盖的是extern
int foo( int x, int y ) ,则模块B找不顶模块A中之函数;反之亦然

 所以,可以就此同样句话概括extern
“C”那多少个宣称的真人真事目的(任何语言中之任何语法特性的降生还无是擅自而也的,来源于真实世界之求使得。大家在思考问题时,不克仅仅待于斯语言是怎开的,还要问一样咨询她怎么要如此做,动机是什么,这样大家得还透彻地领略多题目):实现C++与C及任何语言的良莠不齐编程。

 

5.extern “C”的惯用法

 (1)在C++中援C语言中之函数和变量,在包含C语言头文件(假诺为cExample.h)时,需举行下列处理:

 extern “C”

{ #include “cExample.h” }

 而以C语言的头文件被,对这个外表函数只好指定为extern类型,C语言中未辅助extern
“C”注明,在.c文件被蕴藏了extern “C”时会晤并发编译语法错误。

 笔者编写的C++引用C函数事例工程中涵盖的老三单公文的源代码如下:

 /* c语言头文件:cExample.h */

 

#ifndef C_EXAMPLE_H

#define C_EXAMPLE_H

extern int add(int x,int y);

#endif /* c语言实现公文:cExample.c */

#include “cExample.h”

int add( int x, int y )

{

  return x + y;

}

 

 // c++实现公文,调用add:cppFile.cpp

 

extern “C” 

{ #include “cExample.h” }

int main(int argc, char* argv[])

{

  add(2,3); 

  return 0;

}

 

 倘诺C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或者讲明接口函数时,应加

extern “C” { }

 (2)在C中引用C++语言中之函数和变量常,C++的条文件需要添加extern
“C”,不过在C语言中无克一向引用讲明了extern
“C”的该头文件,应该仅仅将C文件上校C++中定义之extern
“C”函数阐明为extern类型。

 笔者编写的C引用C++函数例子工程中含有的老三单公文的源代码如下:

 //C++头文件 cppExample.h

#ifndef CPP_EXAMPLE_H

#define CPP_EXAMPLE_H extern “C” int add( int x, int y );

#endif
//C++实现文件 cppExample.cpp

#include “cppExample.h”

int add( int x, int y )

return x + y; }

 

 /* C实现公文 cFile.c

 

/* 这样会面编译出错:#include “cExample.h” */

extern int add( int x, int y );

int main( int argc, char* argv[] )

{

  add( 2, 3 ); 

  return 0;

}