以内的关联和效率的不相同,环境下行使动态链接库dll的详解

c++调用c#写的DLL;

1,什么是dll文件?

.h头文件是编写翻译时必须的,lib是链接时索要的,dll是运作时索要的。

在 C# 中通过 P/Invoke 调用Win32 DLL

此小说演示了建立c#的dll;

DLL(Dynamic Link
Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是1个完好的可执行文件,它们被剪切成一些针锋绝对独立的动态链接库,即DLL文件,放置于系统中。当大家实施某3个程序时,相应的DLL文件就会被调用。二个应用程序可接纳三个DLL文件,1个DLL文件也大概被不相同的应用程序使用,那样的DLL文件被叫作共享DLL文件。

外加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成
LIB文件。倘若要完王炯代码的编写翻译和链接,有头文件和lib就够了。假如也使动态连接的程序运维起来,有dll就够了(放在Debug文件夹里)。在支付和调剂阶段,当然最佳都有。

 

c++建立工程,引进dll;

二,托管dll和非托管dll差别是怎么?

.h .lib .dll叁者的涉嫌是:

大家在实质上中国人民解放军海军事工业程高校业作学习C#的时候,只怕会问:为何大家要为壹些早已存在的机能(比如
Windows中的一些意义,C++中曾经编写制定好的有个别格局)要重新编排代码,C#有未有主意能够向来都用这个原本已经存在的效劳吗?答案是肯定的,大家可以经过C#中的DllImport直接调用那个意义。
DllImport所在的名字空间 using System.Runtime.Interop瑟维斯s;
MSDN中对DllImportAttribute的解说是那样的:可将该属性应用于艺术。DllImportAttribute
属性提供对从非托管 DLL
导出的函数举行调用所必备的消息。作为最低须要,必须提供带有入口点的 DLL
的称呼。
DllImport 属性定义如下:
namespace System.Runtime.InteropServices
{
  [AttributeUsage(AttributeTargets.Method)]
  public class DllImportAttribute: System.Attribute
  {
   public DllImportAttribute(string dllName) {…}
   public CallingConvention CallingConvention;
   public CharSet CharSet;
   public string EntryPoint;
   public bool ExactSpelling;
   public bool PreserveSig;
   public bool SetLastError;
   public string Value { get {…} }
  }
}
  说明:
  一、DllImport只可以放置在章程证明上。
  2、DllImport具有单个定位参数:钦赐包括被导入方法的 dll 名称的
dllName 参数。
  3、DllImport具有七个命名参数:
   a、CallingConvention 参数提示入口点的调用约定。假诺未钦点CallingConvention,则运用暗中同意值 CallingConvention.Winapi。
   b、CharSet 参数提醒用在入口点中的字符集。倘使未内定CharSet,则利用默许值 CharSet.Auto。
   c、EntryPoint 参数给出 dll 中入口点的名称。假诺未指定EntryPoint,则使用办法本人的名目。
   d、ExactSpelling 参数指示 EntryPoint
是或不是必须与提醒的入口点的拼写完全相配。假若未钦命ExactSpelling,则采用私下认可值 false。
   e、PreserveSig
参数提示方法的签署应当被封存照旧被转移。当签名被更换时,它被更换为2个拥有
HRESULT 重返值和该重回值的一个名字为 retval
的附加输出参数的署名。借使未钦命 PreserveSig,则应用暗中同意值 true。
   f、SetLastError 参数提醒方法是不是保留 Win3二”上1荒谬”。尽管未钦命SetLastError,则应用私下认可值 false。
  四、它是1回性属性类。
  五、别的,用 DllImport 属性修饰的方法必须有所 extern 修饰符。

不能够一蹴而就的标题:

托管DLL正是能够在集体语言运营库(Common
Language
Runtime,简称CL劲客)中能够直接引用的,并且扩展为“DLL”的公文。具体所指正是包装各个命名空间所在的DLL文件,如System.dll等。非托管DLL正是平时所的动态链接库等,其中就总结了包装全体Windows
API函数的DLL文件。各类非托管DLL中的函数在国有语言运维库中无法一贯被调用,而须要经过.Net框架提供的“平台调用”服务后才得以。(简单来讲就是.net环境下转移的动态链接库为托管dll,相反则为非托管dll)

H文件功用是:声明函数接口

 

点名dll的门径,在代码里面平昔写 #using “xxx.dll” 必须求在动用路径
#using “../bin/debug/xxx.dll”

三,托管dll和非托管dll如何行使?

DLL文件成效是: 函数可实施代码

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

 

托管dll在VS环境下行使相对简单,能够在档次名上右击选拔充足应用的不二等秘书籍导入dll,本文那里不作详解。非托管dll的应用手续及如下:

当大家在友好的次序中引用了1个H文件里的函数,编链器怎么通晓该调用哪些DLL文件呢?这便是LIB文件的成效:
告诉链接器
调用的函数在哪些DLL中,函数执行代码在DLL中的什么地方,这也正是怎么需求增大正视项
.LIB文件,它起到大桥的成效。要是生成静态库文件,则并未有DLL
,唯有lib,那时函数可实行代码部分也在lib文件中

 

1-建立c#的dll,过程略;

壹,需求检讨选拔的dll的目的平台(Any
Cpu,x八陆,x6四),在项目属性生成选项卡中甄选与dll相呼应的对象平台。因为托管dll是在.net的条件下转移的,转换为机器语言后能够自动识别目标平台即有框架帮忙解释,而非托管不可见和好辨认要求人工的装置。

当下以lib后缀的库有三种,一种为静态链接库(Static
Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import
Libary,以下简称“导入库”)。静态库是三个要么多少个obj文件的卷入,所以有人干脆把从obj文件生成lib的历程称为Archive,即集合到1同。比如您链接2个静态库,即便内部有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。动态库一般会有照应的导入库,方便程序静态载入动态链接库,不然你或者就必要协调LoadLibary调入DLL文件,然后再手工业GetProcAddress获得对应函数了。有了导入库,你只供给链接导入库后依照头文件函数接口的宣示调用函数就能够了。导入库和静态库的区别一点都不小,他们本质是不1样的事物。静态库自身就富含了事实上履行代码、符号表等等,而对此导入库而言,其实际的执行代码位于动态库中,导入库只含有了地点符号表等,确定保证程序找到呼应函数的1对基本地址音讯。

   
DllImport
是System.Runtime.InteropServices命名空间下的三个属性类,其效果是提供从非托管DLL导出的函数的至关重要调用新闻。
    DllImport属性应用于艺术,须求最少要提供带有入口点的dll的名号。
    DllImport的概念如下:

美高梅开户网址 1

2,使用DllImport导入非托管dll。

貌似的动态库程序有lib文件和dll文件。lib文件是必须在编写翻译期就连接受应用程序中的,而dll文件是运作期才会被调用的。借使有dll文件,那么相应的lib文件壹般是一些索引音信,具体的贯彻在dll文件中。倘若唯有lib文件,那么这几个lib文件是静态编写翻译出来的,索引和兑现都在中间。静态编写翻译的lib文件有利益:给用户安装时就不必要再挂动态库了。但也有弱点,就是造成应用程序比较大,而且失去了动态库的油滑,在本子升级时,同时要宣布新的应用程序才行。在动态库的情形下,有多个公文,而三个是引进库(.LIB)文件,1个是DLL文件,引进库文件包涵被DLL导出的函数的称呼和地点,DLL包罗实际的函数和数量,应用程序使用LIB文件链接到所须求利用的DLL文件,库中的函数和数码并不复制到可执行文件中,因而在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内部存款和储蓄器地址,那样当2个或七个应用程序运营是再把程序代码和被调用的函数代码链接起来,从而节省了内部存款和储蓄器财富。从地点的辨证能够看来,DLL和.LIB文件必须随应用程序一起发行,不然应用程序将会发生错误。

        [AttributeUsage(AttributeTargets.Method)] 
     public class DllImportAttribute: System.Attribute 
     { 
      public DllImportAttribute(string dllName) {…} //定位参数为dllName 
 public CallingConvention CallingConvention; //入口点调用约定 
 public CharSet CharSet;                                   //入口点采用的字符接 
 public string EntryPoint;                                  //入口点名称 
 public bool ExactSpelling;                               //是否必须与指示的入口点拼写完全一致,默认false 
 public bool PreserveSig;                                  //方法的签名是被保留还是被转换 
 public bool SetLastError;                                  //FindLastError方法的返回值保存在这里 
 public string Value { get {…} } 
     } 

 

DllImport会遵照以下3种顺序查找dll文件:
一)、exe所在目录;
二)、System3二索引(系统目录);


用法示例:

2.改动出口路径输出为 ../bin/debug; ../bin/release 方便c++能够一定找到

三)、环境变量目录。(即要求将dll及依赖文件放到二个目录中的任何3个索引中)。

静态链接库(Lib)与动态链接库(DLL)的分别

    [DllImport("kernel32")] 
    private static extern long WritePrivateProfileString(string section,string key,string val,string filePath);

美高梅开户网址 2

DllImport的导入规则:
一)、方法名与Win
API完全一致。如若在C#中调用时体现完全分化的不二等秘书诀名称,则供给引进EntryPoint属性,使用外号展现。
二)、函数除急需DllImport类修饰符外,还索要注解public
static extern类型。
叁)、函数重临值和参数必须和调用的API的一心平等。

    
静态连接库正是把(lib)文件中用到的函数代码直接链接进目的程序,程序运转的时候不再须要别的的库文件;动态链接正是把调用的函数所在文书模块(DLL)和调用函数在文书中的地方等音信链接进目的程序,程序运转的时候再从DLL中检索对应函数代码,由此需求相应DLL文件的帮忙。

    以上是用来写入ini文件的一个win32api。
    
   
用此方式调用Win32API的数据类型对应:DWOLANDD=int或uint,BOOL=bool,预约义常量=enum,结构=struct。
 

 

肆)、必须引进System.Runtime.Interop瑟维斯s命名空间。

静态链接库与动态链接库都以共享代码的办法,假诺利用静态链接库,则不管你愿不愿意,lib
中的指令都全体被直接包罗在最后生成的 EXE 文件中了。不过若选取 DLL,该
DLL 不必被含有在结尾 EXE 文件中,EXE
文件执行时得以“动态”地引用和卸载这一个与 EXE 独立的 DLL
文件。静态链接库和动态链接库的别的一个有别于在于静态链接库中不能够再包蕴别的的动态链接库也许静态库,而在动态链接库中还足以再包括其余的动态或静态链接库。

DllImport会依据顺序自动去寻找的地点: 一、exe所在目录 二、System3贰目录
三、环境变量目录所以只须求您把引用的DLL 拷贝到那八个目录下
就能够不用写路径了
或然能够如此server.MapPath(.\bin\*.dll)web中的,同时也是应用程序中的
后来发现用[DllImport(@”C:\OJ\Bin\Judge.dll”)]这么钦定DLL的相对路径就能够平时装载。 这么些难点最常出现在应用
第三方非托管DLL组件的时候,笔者的也如出1辙是此时出的标题,Asp.Net
Team的法定化解方案如下: 首先供给肯定你引用了何等组件,那么些是托管的,哪些是非托管的.托管的很好办,直接被利用的内需引用,直接使用的须求拷贝
到bin目录下.非托管的处理会比较麻烦.实际上,你拷贝到bin未有其余赞助,因为CLMurano会把公文拷贝到三个一时半刻目录下,然后在那运维web,而CL奥迪Q7只会拷贝托管文件,那正是为啥大家掌握把非托管的dll放在了bin下却依然提醒无法加载模块了.  具体做法如下:  首先我们在服务器上随便找个地点新建二个目录,假若为C:\DLL  然后,在环境变量中,给Path变量添加这么些目录  最终,把装有的非托管文件都拷贝到C:\DLL中.  只怕更索性的把DLL放到system32目录  对于能够友善配置的应用程序,那样未偿不是多少个化解办法,可是,要是大家用的是杜撰空间,大家是不可能把注
册PATH变量也许把我们和好的DLL拷到system3贰目录的。同时大家也不肯定知道我们的Dll的情理路径。  DllImport里面只可以用字符
串常量,而不可见用Server.MapPath(@”~/Bin/Judge.dll”)来规定物理路径。ASP.NET中要运用DllImport
的,必须在先“using
System.Runtime.InteropServices;”可是,小编发现,调用那种”非托管Dll”非常的慢,只怕是因为自个儿的措施要求长途验证
吧,可是事实上是太慢了。经过壹翻钻探,终于想到了一个完善的消除办法首先我们用

三.在解决方案添加C++工程,进程略

DllImport的可选属性参数表达:
EntryPoint
        钦赐要调用的 DLL 入口点。 
SetLastError
      判断在执行该办法时是不是出错(使用 马尔斯hal.GetLastWin3二Error API
函数来规定)。C#中暗中同意值为
false。
CharSet
           控制名称及函数中字符串参数的编码方式。默许值为
CharSet.Ansi。
ExactSpelling
     是还是不是修改入口点以对应差别的字符编码格局。
CallingConvention
 指定用于传递格局参数的调用约定。暗中同意值为
WinAPI。该值对应于基于30位英特尔平台的 __stdcall。
BestFitMapping
    是或不是启用顶级映射功效,私下认可为 true。最好映射效用提供在未曾相配项时,自动提供相称的字符。不能够映射的字符通常转换为暗中认可的“?”。

“每贰个lib文件正是多少函数(借使唯有函数)的定义”
lib库有三种,一种是包罗了函数所在DLL文件和文件中等学校函授数地方的新闻,称为导出库;一种是含有函数代码自个儿,一般现有的DLL,用的是前一种库;从前在DOS下的TC/BC等,是后1种库。包罗函数原型表明的,是头文件(.h)。

[DllImport("kernel32.dll")] 
private extern static IntPtr LoadLibrary(String path); 

[DllImport("kernel32.dll")] 
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName); 

[DllImport("kernel32.dll")] 
private extern static bool FreeLibrary(IntPtr lib);

 

PreserveSig
       托管方法签
名是不是转换到再次回到HRESULT,暗中认可值为 true(不应转换签名)。并且再次来到值有二个叠加的
[out, retval] 参数的非托管签名。  

“通过#include包罗那些函数评释的头文件后,我们的应用程序就能够行使lib文件中的函数”

独家赢得了LoadLibrary和GetProcAddress函数的地点,再经过这多个函数来取得大家的DLL里面包车型客车函数。
我们能够先用Server.MapPath(@”~/Bin/Judge.dll”)来取得我们的DLL的大体路径,然后再用LoadLibrary举行载入,最终用GetProcAddress取得要用的函数地址

四.新加上的C++工程,引用DLL,同时引进名字空间;

ThrowOnUnmappableChar
    控制对转移为 ANSI ‘?’ 字符的不行映射的 Unicode
字符引发那个。

还要内定编写翻译器链接相应的库文件。在IDE环境下,一般是2回钦定所有应用的库文件,编写翻译器自个儿摸索每一种模块供给的库;在指令行编写翻译环境下,必要钦点每一个模块调用的库。

以下自定义类的代码实现LoadLibrary的装载和函数调用:

  •   引用库使用 #using “xxx.dll” 那里需求制订dll的绝对路径
  • #pragma managed;  // 告诉编译器,将应用托管代码

  • using namespace CsDll002;  // 引进名字空间

4,c#与c++、c动态链接库的参数怎么样对应?

“那她和一贯付出这几个函数定义的文书,比如.cpp文件,和头文件有啥样差异,静态链接库有如何用”
cpp文件是源代码,库文件是编写翻译后的2进制代码,比如您能够调用Windows的API,但是无法收看其源代码壹样。

 public class DllInvoke  
    {             
        [DllImport("kernel32.dll")]  
        private extern static IntPtr LoadLibrary(String path); 

        [DllImport("kernel32.dll")]    
        private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);  

        [DllImport("kernel32.dll")]      
        private extern static bool FreeLibrary(IntPtr lib);      

        private IntPtr hLib;    

        public DllInvoke(String DLLPath)    
        {            
            hLib = LoadLibrary(DLLPath);   
        }        

        ~DllInvoke()      
        {         
            FreeLibrary(hLib);   
        }         

        //将要执行的函数转换为委托   
 public Delegate Invoke(String APIName,Type t)      
        {            
            IntPtr api = GetProcAddress(hLib, APIName);    
            return (Delegate)Marshal.GetDelegateForFunctionPointer(api,t);      
        } 
    }

 

以内的关联和效率的不相同,环境下行使动态链接库dll的详解。C
C# 备注

“还有不清楚的是,静态链接库中的lib文件只要使用,则全体lib文件的故事情节都放进了exe文件中,那它是被编写翻译进去照旧链接的时候总是进去的吗?”
是在链接的时候将lib链接到指标代码中。

上边代码举行调用

美高梅开户网址 3

short int16 短整型

静态链接库(Lib)
在VC++陆.0中new三个称呼为libTest的static library工程,

 public delegate int Compile(String command, StringBuilder inf); 
            //编译 
            DllInvoke dll = new DllInvoke(Server.MapPath(@"~/Bin/Judge.dll")); 
            Compile compile = (Compile)dll.Invoke("Compile", typeof(Compile)); 
            StringBuilder inf; 
            compile(@“gcc a.c -o a.exe“,inf);//这里就是调用我的DLL里定义的Compile函数

5.行使类库

int int32 整型

并新建lib.h和lib.cpp七个公文,lib.h和lib.cpp的源代码如下:

 

 尖号表示托管;那里演示了再次回到值使用引用,和C++调用引用1样,不需求钦赐特殊字符;

long int64 长整型

//文件:lib.h
#ifndef LIB_H
#define LIB_H
extern “C” int add(int x,int
y);   //注脚为C编写翻译、连接格局的外部函数
#endif

 

与C#区别,如果c# 写的函数是 int  add(int a, int b, ref int resut) 
调用时需求 add(一, 贰, ref result);那里C++没有这么些语法供给。

&
ref 取地址

//文件:lib.cpp
#include “lib.h”
int add(int x,int y)
{
return x + y;
}

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

 

* ref 指针

  编译这一个工程就得到了3个.lib文件,这几个文件正是三个函数库,它提供了add的机能。将头文件和.lib文件提交给用户后,用户就足以一贯运用在这之中的add函数了。

DllImport的用法:
DllImport(“MyDllImport.dll”)]
private static extern int mySum(int a,int b);

c#中期维修饰符ref、out的职能及效率

  标准Turbo
C二.0中的C库函数(大家用来的scanf、printf、memcpy、strcpy等)就来源于那种静态库。

一 在C#次第设计中选择Win3二类库
常用对应项目:
一、DWOLacrosseD 是 四 字节的平头,因而大家能够使用 int 或 uint 作为 C#
对应类型。
2、bool 类型与 BOOL 对应。

ref
供给参数在传递给函数前要开头化,out则不供给,常见于阳台调用中。out和ref传递的都以引用而不是值,out侧重于出口使用此前不需赋值而ref在行使在此以前要求赋值,其余那七个重点字能够变相完毕使一个措施输出三个值。ref能够把参数的数值传递进函数,但是out是要把参数清空,正是说你不可能把二个数值从out传递进入的,out进去后,参数的数值为空,所以您必须起始化一次。那几个正是三个的区分,可能说就如有个别网络好友说的,ref是有进有出,out是只出不进。表达是引用的传递。

下边来看望怎么选取这么些库,在libTest工程所在的工作区内new八个libCall工程。libCall工程仅包蕴3个main.cpp文件,它以身作则了静态链接库的调用方法,其源代码如下:

演示壹:调用 Beep() API 来发出声音
Beep() 是在 kernel3二.lib 中定义的,在MSDN 中的定义,Beep具有以下原型:
BOOL Beep(DWOENCORED dwFreq, // 声音频率
DWO揽胜D dwDuration // 声音持续时间);
用 C# 编写以下原型:
[DllImport(“kernel32.dll”)]
public static extern bool Beep(int frequency, int duration);

example:

#include <stdio.h>
#include “..\lib.h”//不可丢失
#pragma comment( lib, “..\\debug\\libTest.lib” )
 //钦赐与静态库1起一而再
int main(int argc, char* argv[])
{
     printf( “2 + 3 = %d”, add( 2, 3 ) );
}
  静态链接库的调用便是这么不难,或者大家每日都在用,但是大家尚无精晓那么些概念。代码中#pragma
comment( lib , “..\\debug\\libTest.lib”
)的意思是指本文件生成的.obj文件应与libTest.lib1起接连

以身作则2:枚举类型和常量
MessageBeep() 是在 user3二.lib 中定义的,在MSDN
中的定义,MessageBeep具有以下原型:
BOOL MessageBeep(UINT uType // 声音类型
);

//命名空间


用C#编排一下原型:
public enum BeepType
{
  SimpleBeep = -1,
  IconAsterisk = 0x00000040,
  IconExclamation = 0x00000030,
  IconHand = 0x00000010,
  IconQuestion = 0x00000020,
  Ok = 0x00000000,
}
uType 参数实际上接受一组预先定义的常量,对于 uType 参数,使用 enum
类型是合乎情理的。
[DllImport(“user32.dll”)]
public static extern bool MessageBeep(BeepType beepType);

using
System.Runtime.InteropServices;

用VC++生成静态库文件
前些天闲着没事做,自个儿写了一点小笔记,不明白对于新手有没用,高手就毫无看了,作为新手的笔者斗胆来刊登2个笔记,正是静态库文件的卷入进程,使用VC++陆.0编写,上面是本文,可能作者的用语并非驴非马

演示三:处理协会
有时笔者要求分明自个儿台式机的电池情况。Win3二 为此提供了电源管理函数,搜索
MSDN 能够找到GetSystemPowerStatus() 函数。
BOOL GetSystemPowerStatus(
  LPSYSTEM_POWER_STATUS lpSystemPowerStatus
);
此函数包括指向某些协会的指针,大家从未对此展开过处理。要处理组织,大家供给用
C# 定义结构。大家从非托管的定义初阶:
typedef struct _SYSTEM_POWER_STATUS {
BYTE  ACLineStatus;
BYTE  BatteryFlag;
BYTE  BatteryLifePercent;
BYTE  Reserved1;
DWORD BatteryLifeTime;
DWORD BatteryFullLifeTime;
} SYSTEM_POWER_STATUS, *LPSYSTEM_POWER_STATUS;
   然后,通过用 C# 类型代替 C 类型来获取 C# 版本。
struct SystemPowerStatus
{
  byte ACLineStatus;
  byte batteryFlag;
  byte batteryLifePercent;
  byte reserved1;
  int batteryLifeTime;
  int batteryFullLifeTime;
}
诸如此类,就足以一本万利地编写出 C# 原型:
[DllImport(“kernel32.dll”)]
public static extern bool GetSystemPowerStatus(
  ref SystemPowerStatus systemPowerStatus);
  
在此原型中,大家用“ref”指明将传递结构指针而不是结构值。那是拍卖通过指针传递的构造的形似方法。
   此函数运转非凡,不过最为将 ACLineStatus 和 batteryFlag 字段定义为
enum:
  enum ACLineStatus: byte
   {
    Offline = 0,
    Online = 1,
    Unknown = 255,
   }
   enum BatteryFlag: byte
   {
    High = 1,
    Low = 2,
    Critical = 4,
    Charging = 8,
    NoSystemBattery = 128,
    Unknown = 255,
   }
请留意,由于组织的字段是部分字节,因而大家应用 byte 作为该 enum
的主干类型

//导入非托管dll

原先大家写C/C++源文件的时候,都以先将依次写好的源文件编写翻译,编写翻译生成的是目的文件机器码,即.obj文件.(指标文件的扩展名不一定是.obj文件).

示范肆:处理字符串

//分配的库处理和连接到数控钦定的IP地址或主机名。

我们调用的标准C/C++函数机器码实际被卷入于标准C/C++静态库文件中的.即这么些增添名称叫.lib的公文中.

二 C# 中调用C++代码
int 类型
[DllImport(“MyDLL.dll”)]
//返回个int 类型
public static extern int mySum (int a1,int b1);
//DLL中申明
extern “C” __declspec(dllexport) int WINAPI mySum(int a2,int b2)
{
//a二 b2不可能改变a一 b一
//a2=..
//b2=…
return a+b;
}

[DllImport(“Fwlib64.dll”,
EntryPoint = “cnc_allclibhndl3”,
CallingConvention=CallingConvention.Cdecl)]

终极链接器将大家编写翻译的顺序指标文件里的机器码和静态库(标准C/C++库)中的函数机器码链接到一起形成2个扩张名字为.exe的可执行文件模块.

//参数字传送递int 类型
public static extern int mySum (ref int a1,ref int b1);
//DLL中申明
extern “C” __declspec(dllexport) int WINAPI mySum(int *a2,int *b2)
{
//能够改变 a壹, b1
*a2=…
*b2=…
return a+b;
}

//short
(const char *ipaddr, unsigned short port, long timeout, unsigned short
*FlibHndl)

在此处大家讲述将C/C++源文件编写翻译链接成2个静态库文件,但它不是可实施模块,它体内含有可举行机器码

DLL 需传入char *类型
[DllImport(“MyDLL.dll”)]
//传入值
public static extern int mySum (string astr1,string bstr1);
//DLL中申明
extern “C” __declspec(dllexport) int WINAPI mySum(char * astr2,char
* bstr2)
{
//改变astr2 bstr 2 ,astr一 bstr一不会被转移
return a+b;
}

private
static extern Int16 cnc_allclibhndl3(ref String ip, UInt16 port, Int64
timeout, ref UInt16 flibHndl);

静态库文件就像是1个储藏室只怕容器,里面封装了1部分可进行机器码.这一个机器码是大家用程序设计语言,比如C/C++源文件编写翻译后生成的机器码.

DLL 需传出char *类型
[DllImport(“MyDLL.dll”)]
// 传出值
public static extern int mySum (StringBuilder abuf, StringBuilder bbuf
);
//DLL中申明
extern “C” __declspec(dllexport) int WINAPI mySum(char * astr,char *
bstr)
{
//传出char *美高梅开户网址 , 改变astr bstr –>abuf, bbuf能够被改变
return a+b;
}

(整理,源小说来源于网络)

1.下边将研商将C/C++源文件编写翻译并链接成一个静态库文件的进度,

DLL 回调函数

在VC++6.0中精选File-New-Win3二 Static
Library,写好工程名成立好办事空间后再选拔菜单中New-File来为工程添加C或然C++
源文件.

BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

假若大家为该工程添加了五个名叫lib_c.c和三个名称为lib_cpp.cpp的源文件

using System;
using System.Runtime.InteropServices;
public delegate bool CallBack(int hwnd, int lParam);
//定义委托函数类型
public class EnumReportApp
{
[DllImport(“user32”)]
public static extern int EnumWindows(CallBack x, int y);
public static void Main() {
CallBack myCallBack = new CallBack(EnumReportApp.Report);
EnumWindows(myCallBack, 0);
}
public static bool Report(int hwnd, int lParam)
{
Console.Write(“Window handle is “);
Console.WriteLine(hwnd); return true;
}
}

//lib_c.c中的内容

DLL 传递结构
BOOL PtInRect(const RECT *lprc, POINT pt);

extern int Add(int x,int y)
//该函数是二个外表函数,任何公文都足以访问它

using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct Point {
public int x;
public int y;
}
[StructLayout(LayoutKind.Explicit)]
public struct Rect
{
[FieldOffset(0)] public int left;
[FieldOffset(4)] public int top;
[FieldOffset(8)] public int right;
[FieldOffset(12)] public int bottom;
}
Class XXXX {
[DllImport(“User32.dll”)]
public static extern bool PtInRect(ref Rect r, Point p);
}

{
    return x+y;

}

extern int data_c
//那是多少个外部全局变量,任何文件能够访问它

//lib_cpp.cpp中的内容

extern “C” int
        reduce(int x,int
y)//那里加了个”C”表示同意C源文件访问这几个C++函数代码

{
    return x-y;

}

extern “C” int data_cpp=2;

专注以下几点

(1)当“extern”关键字修饰在函数或全局变量的定义中时,表示该函数或全局变量任何文件能够访问,“extern”关键字可以省略不写,缺省下正是”extern”

 
当“extern”关键字修饰在函数注解或全局变量表明中时,表示限定当前文件只好引用用“extern”关键字修饰定义的函数或全局变量.

(贰)当”static”关键字修饰在函数或全局变量的定义中时,表示该函数或全局变量只好由本文件中加了”static”关键字修饰的函数申明或全局变量证明来引用.

 
当”static”关键字修饰在函数表明或全局变量注脚中时,表示限定当前文件只可以引用用“static”关键字修饰定义的函数或全局变量.

(三)在CPP源文件的函数和全局变量定义中加了个”C”表示同意C源文件访问该函数和大局变量.假使是C++源文件访它们的话则可加可不加.注意这”C”要大写.

接下去就要将写好的C/C++源文件举办编译和链接,最终会变动二个恢弘名称叫.lib的文件.该文件正是静态库文件了,该静态库文件是不能一贯运维的,大家所编写翻译的C/C++源文件的机器码就曾经被包裹进这么些用VC++六.0创设的静态库文件之中去了.

二.什么样将编写制定好的静态库文件像使用C/C++标准库那样选择,上面将连续研商

一.用VC++6.0新建叁个工程名字为TEST,添加3个名称叫TEST.c的源文件到该工程,因为大家将测试一下,将大家编辑的库文件里的函数只怕全局变量的机器码链接到大家这一个TEST.c源文件中去,倘若大家转移的库文件名称为TEST.lib,先拷贝如下范例代码到TEST.c中

//TEST.c

#include <stdio.h>

extern int
Add(int x,int y); //当前文件只可以访问“extern”关键字修饰定义的Add函数

extern int
reduce(int x,int y);//
//当前文件只可以访问“extern”关键字修饰定义的reduce函数

#pragma comment(lib,”TEST.lib”)
//提醒链接器到字符串所表示的文件路径中去找库文件

int main()

{
    printf(“%d\n”,Add(2,3));
    printf(“%d\n”,reduce(3,2));
    return 0;

}

此地大家要评释静态库中已知的函数或全局变量的评释

#pragma
comment(lib,”TEST.lib”)那条指令告诉链接器到字符串所代表的路径下去找库文件,那里自身将库文件放到了当下工程目录下.也能够不写那句.

再有1种办法,能够向来在VC++陆.0中装置依次选拔tools、options、directories、library
files菜单或选拔,填入库文件路径(只键入库文件所在目录路径而不能够输入库文件名),那只是报告链接器库文件所在目录的路线,还没告诉链接器库文件名,方法是VC++六.0中安装依次选择project-settings-link
在object/library modules: 这栏输入库文件名字然后就OK了

贰.当用C++源文件的目的文件和库文件的代码链接时有一点小改变,那里就不浪费口舌了,倘使大家新建了叁个工程并添加了三个名称叫TEST.CPP的源文件,拷贝如下范例代码到TEST.CPP中

//TEST.cpp

#include <stdio.h>

extern “C” int
       Add(int x,int y); //表示援引的是C函数代码

extern int
      reduce(int x,int y);

#pragma comment(lib,”TEST.lib”)

int main()

{
    printf(“%d\n”,Add(2,3));
    printf(“%d\n”,reduce(3,2));
    return 0;

}

在那个C++源文件里引用C函数代码同样要加个”C”,可是在C源文件引用C++函数代码不能够加”C++”,编写翻译会报错,只可以在C++文件函数定义中加”C”.

唯有C++才帮忙那种引用格局,也许因为只有C++兼容C而从不C包容C++那一原则.

 

 

.h用于编写翻译阶段的审核,如在math.h中有函数证明:
int abs(int);
不过在运用中写为
#include <math.h>
…abs(3,5);
编译器阶段就会检查实验出荒唐。

.dll用于周转阶段,如调用SetWindowText()函数等,供给在user32.dll中找到该函数。DLL能够大致认为是一种含有供旁人调用的函数和财富的可执行文件。

.lib用于链接阶段,在链接各部分目的文件(平日为.obj)到可执行文件(平日为.exe)进度中,供给在.lib文件中摸索动态调用函数(1般为DLL中的函数)的地方新闻,此时内需在lib文件中搜寻,如搜寻SetWindowText()函数的地点偏移就须求查找user3二.lib文件。(.lib也可用于静态链接的内嵌代码)

 

lib和dll文件的区分和挂钩    
   
 
.dll是在你的程序运营的时候才连接的文书,由此它是1种相比较小的可执行文件格式,.dll还有此外的文件格式如.ocx等,全体的.dll文件都以可实施。
 
   
 
.lib是在你的先后编写翻译连接的时候就总是的公文,由此你必须告知编写翻译器连接的lib文件在那里。1般的话,与动态连接文件相对照,lib文件也被称呼是静态连接库。当您把代码编写翻译成那三种格式的公文时,在事后他们就不容许再被改成。假诺您想利用lib文件,就亟须:
 
  一?   包含多少个一唱一和的头文件报告编写翻译器lib文件之中的具体内容  
  贰?   设置lib文件允许编写翻译器去找寻已经编写翻译好的2进制代码  
   
 
假若你想从你的代码分离三个dll文件出来代替静态连接库,如故须要一个lib文件。那些lib文件将被连接受程序告诉操作系统在运维的时候你想用到怎么着dll文件,一般情形下,lib文件里有对应的dll文件的名字和八个指明dll输出函数入口的顺序表。要是不想用lib文件或然是绝非lib文件,能够用WIN3二  
API函数LoadLibrary、GetProcAddress。事实上,大家能够在Visual   C++  
IDE中以二进制情势打开lib文件,大多情形下汇合到ASCII码格式的C++函数或局地重载操作的函数名字。
 
   
  一般大家最要害的关于lib文件的麻烦正是出新unresolved   symble  
那类错误,那就是lib文件三番五次错误可能未有包括.c、.cpp文件到工程里,关键是若是在C++工程里用了C语言写的lib文件,就必需求如此含有:
 
  extern   “C”  
  {  
  #include   “myheader.h”  
  }  
 
那是因为C语言写的lib文件并未有C++所必须的名字破坏,C函数不可能被重载,由此连接器会出错。

 

C语言中有1部分函数不须求举办编写翻译,有1对函数也可以在四个文本中央银行使。壹般的话,这一个函数都会执行1些专业职务,如数据库输入/输出操作或显示屏控制等。能够优先对这么些函数进行编写翻译,然后将它们放置在壹部分奇异的靶子代码文件中,这一个目的代码文件就称为库。库文件中的函数能够透过三番五次程序与应用程序进行连接。那样就不必在每一回开发顺序时都对那么些通用的函数举行编译了。  
 
   
 
  不一致档次的应用程序将会动用分歧的函数库。例如:libdbm库中组包括了对数据库文件举行走访的dbm函数,要求对数据库进行操作的程序就会与该库举办再而三。数学应用程序将采纳数学库libm,X-Windows应用程序将采纳Xlib库,libX1壹。此外,全部的先后都将动用专业的C函数库。libc,该库中带有了诸好内部存储器管理或输入输出操作的大旨函数,那一个库都存放在/usr/lib那一个体系公用的目录中,系统中的任何用户都足以行使那几个库。当然用户也能够成立本人专用的库函数,供自身或别的钦命的人口选择。  
 
   
 
  库能够有二种选择的花样:静态、共享和动态。静态库的代码在编译时就已一连到开发职员开发的应用程序中,而共享库只是在先后开始运行时才载入,在编写翻译时,只是简单地钦定供给运用的库函数。动态库则是共享库的另1种变更情势。动态库也是在程序运维时载入,但与共享库分化的是,使用的库函数不是在程序运转开端,而是在程序中的语句须要利用该函数时才载入。动态库能够在程序运营时期保释动态库所占用的内部存款和储蓄器,腾出空间供其余程序选用。由于共享库和动态库并不曾在程序中回顾库函数的始末,只是包涵了对库函数的引用,由此代码的范围比较小。

 

lib是静态库,dll一般是动态链接库(也有希望是别的)

比如说要编写翻译个exe,lib在编译的时候就会被编写翻译到exe里,作为程序的1有的

而dll是不被编译进去,是运作的时候才调入的(或许是exe刚运营就调入,也说不定运维了大体上才调入)

用法,lib要求个.lib文件和一个.h文书,程序平日使用.h的函数,在链接选项里加入.lib文件就ok

dll用法有2种,1是 .h + .lib +
.dll的,用法和前边1样,中间的lib是个换车,运转的时候会调用dll
贰是:直接用dll,须求知道dll的函数定义,用LoadLibrary和GetProcAddress把函数指针取出来,看msdn的例子吗

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图