【4858.com】条件下利用动态链接库dll的详解,之间的关系和效应的界别

By admin in 4858.com on 2019年3月29日

c++调用c#写的DLL;

1,什么是dll文件?

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

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

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

DLL(Dynamic Link
Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是1个全部的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们履行某叁个程序时,相应的DLL文件就会被调用。叁个应用程序可应用多少个DLL文件,1个DLL文件也恐怕被区别的应用程序使用,那样的DLL文件被号称共享DLL文件。

叠加信赖项的是.lib不是.dll,若生成了DLL,则一定也生成
LIB文件。假若要旗开马到源代码的编译和链接,有头文件和lib就够了。要是也使动态连接的程序运维起来,有dll就够了(放在Debug文件夹里)。在开发和调节和测试阶段,当然最佳都有。

 

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

2,托管dll和非托管dll差异是何等?

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

我们在实质上中国人民解放军海军事工业程高校业作学习C#的时候,大概会问:为啥我们要为一些业已存在的功能(比如
Windows中的一些效率,C++中早就编写制定好的局地艺术)要再一次编写代码,C#有没有方法能够直接都用那一个本来已经存在的效果吗?答案是自然的,大家能够透过C#中的DllImport直接调用这几个功用。
【4858.com】条件下利用动态链接库dll的详解,之间的关系和效应的界别。DllImport所在的名字空间 using System.Runtime.InteropServices;
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只好放置在措施注明上。
  二 、DllImport具有单个定位参数:内定蕴含被导入方法的 dll 名称的
dllName 参数。
  叁 、DllImport具有八个命名参数:
   a、CallingConvention 参数提示入口点的调用约定。假诺未钦点CallingConvention,则应用私下认可值 CallingConvention.Winapi。
   b、CharSet 参数提示用在入口点中的字符集。借使未指定CharSet,则动用暗中同意值 CharSet.Auto。
   c、EntryPoint 参数给出 dll 中入口点的名号。借使未钦点EntryPoint,则利用方法自己的称号。
   d、ExactSpelling 参数提示 EntryPoint
是还是不是必须与提示的入口点的拼写完全匹配。若是未指定ExactSpelling,则使用暗许值 false。
   e、PreserveSig
参数提醒方法的签字应当被封存依旧被转移。当签名被更换时,它被更换为四个怀有
HRESULT 再次回到值和该重临值的三个名为 retval
的附加输出参数的签署。要是未钦定 PreserveSig,则应用默许值 true。
   f、SetLastError 参数提示方法是不是保留 Win32″上一谬误”。借使未钦点SetLastError,则使用暗许值 false。
  四 、它是1次性属性类。
  伍 、其它,用 DllImport 属性修饰的措施必须持有 extern 修饰符。

不能缓解的题材:

托管DLL正是力所能及在公私语言运维库(Common
Language
Runtime,简称CLCR-V)中可知平素引用的,并且扩展为“DLL”的文件。具体所指就是包裹各样命名空间所在的DLL文件,如System.dll等。非托管DLL便是日常所的动态链接库等,当中就包蕴了包装全部Windows
API函数的DLL文件。各类非托管DLL中的函数在国有语言运营库中无法直接被调用,而必要经过.Net框架提供的“平台调用”服务后才得以。(一言以蔽之正是.net环境下转移的动态链接库为托管dll,相反则为非托管dll)

H文件成效是:注明函数接口

 

点名dll的路子,在代码里面一贯写 #using “xxx.dll” 必须求在应用路径
#using “../bin/debug/xxx.dll”

3,托管dll和非托管dll怎样选拔?

DLL文件作用是: 函数可实施代码

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

 

托管dll在VS环境下利用相对不难,能够在项目名上右击选拔丰富应用的方法导入dll,本文那里不作详解。非托管dll的采纳手续及如下:

当大家在投机的次序中引用了一个H文件里的函数,编链器怎么驾驭该调用哪些DLL文件呢?那便是LIB文件的职能:
告诉链接器
调用的函数在哪些DLL中,函数执行代码在DLL中的什么地点,那也正是为啥供给增大依赖项
.LIB文件,它起到大桥的听从。假若生成静态库文件,则从未DLL
,唯有lib,那时函数可实施代码部分也在lib文件中

 

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

1,供给检讨接纳的dll的对象平台(Any
Cpu,x86,x64),在品种属性生成选项卡中挑选与dll相呼应的靶子平台。因为托管dll是在.net的条件下转移的,转换为机器语言后能够自动识别指标平台即有框架协理解释,而非托管不可见和好辨认需求人工的设置。

眼下以lib后缀的库有二种,一种为静态链接库(Static
Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import
Libary,以下简称“导入库”)。静态库是多少个要么三个obj文件的包裹,所以有人干脆把从obj文件生成lib的进程称为Archive,即集合到一块。比如你链接三个静态库,假设中间有错,它会规范的找到是哪个obj有错,即静态lib只是壳子。动态库一般会有照应的导入库,方便程序静态载入动态链接库,不然你恐怕就须要协调LoadLibary调入DLL文件,然后再手工业GetProcAddress获得对应函数了。有了导入库,你只须要链接导入库后依照头文件函数接口的宣示调用函数就足以了。导入库和静态库的界别很大,他们本质是不一致的事物。静态库本人就带有了实际施行代码、符号表等等,而对于导入库而言,其实际的进行代码位于动态库中,导入库只含有了地点符号表等,确定保证程序找到呼应函数的片段大旨地址信息。

   
DllImport
是System.Runtime.InteropServices命名空间下的一个属性类,其功用是提供从非托管DLL导出的函数的画龙点睛调用音讯。
    DllImport属性应用于方法,供给最少要提供含有入口点的dll的称号。
    DllImport的概念如下:

4858.com 1

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

貌似的动态库程序有lib文件和dll文件。lib文件是必须在编写翻译期就连接受应用程序中的,而dll文件是运作期才会被调用的。假设有dll文件,那么相应的lib文件一般是一些索引音讯,具体的兑今后dll文件中。如若唯有lib文件,那么这一个lib文件是静态编写翻译出来的,索引和促科隆在里头。静态编写翻译的lib文件有裨益:给用户设置时就不须要再挂动态库了。但也有通病,正是致使应用程序相比大,而且失去了动态库的灵活性,在本子升级时,同时要发布新的应用程序才行。在动态库的景况下,有八个文本,而1个是引入库(.LIB)文件,一个是DLL文件,引入库文件包罗被DLL导出的函数的称号和任务,DLL包蕴实际的函数和多少,应用程序使用LIB文件链接到所急需选择的DLL文件,库中的函数和数量并不复制到可执行文件中,因而在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内部存款和储蓄器地址,那样当四个或三个应用程序运转是再把程序代码和被调用的函数代码链接起来,从而节省了内部存储器能源。从地方的认证能够看来,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文件:
1)、exe所在目录;
2)、System32索引(系统目录);


用法示例:

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

3)、环境变量目录。(即供给将dll及依赖文件放到1个目录中的任何一个目录中)。

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

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

4858.com 2

DllImport的导入规则:
1)、方法名与Win
API完全相同。假如在C#中调用时展现完全不一样的方法名称,则供给引入EntryPoint属性,使用外号呈现。
2)、函数除必要DllImport类修饰符外,还索要表明public
static extern类型。
3)、函数再次回到值和参数必须和调用的API的完全一样。

    
静态连接库正是把(lib)文件中用到的函数代码直接链接进指标程序,程序运营的时候不再必要任何的库文件;动态链接便是把调用的函数所在文件模块(DLL)和调用函数在文书中的地点等消息链接进目标程序,程序运维的时候再从DLL中追寻对应函数代码,因而要求相应DLL文件的支撑。

    以上是用来写入ini文件的多少个win32api。
    
   
用此措施调用Win32API的数据类型对应:DWO翼虎D=int或uint,BOOL=bool,预订义常量=enum,结构=struct。
 

 

4)、必须引入System.Runtime.InteropServices命名空间。

静态链接库与动态链接库都是共享代码的点子,借使选拔静态链接库,则不管你愿不愿意,lib
中的指令都全体被直接包罗在终极生成的 EXE 文件中了。然则若使用 DLL,该
DLL 不必被含有在结尾 EXE 文件中,EXE
文件执行时得以“动态”地引用和卸载那么些与 EXE 独立的 DLL
文件。静态链接库和动态链接库的其余一个有别于在于静态链接库中无法再包罗别的的动态链接库只怕静态库,而在动态链接库中还足以再包括其余的动态或静态链接库。

DllImport会遵照顺序自动去追寻的地点: ① 、exe所在目录 贰 、System32索引
三 、环境变量目录所以只要求你把引用的DLL 拷贝到那八个目录下
就足以不用写路径了
可能能够这么server.MapPath(.\bin\*.dll)web中的,同时也是应用程序中的
后来发现用[DllImport(@”C:\OJ\Bin\Judge.dll”)]诸如此类钦赐DLL的相对路径就足以健康装载。 那么些难点最常出现在动用
第一方非托管DLL组件的时候,小编的也一致是此时出的标题,Asp.Net
Team的官方解决方案如下: 首先供给肯定你引用了哪些组件,那个是托管的,哪些是非托管的.托管的很好办,间接被选取的内需引用,直接使用的内需拷贝
到bin目录下.非托管的处理会相比较麻烦.实际上,你拷贝到bin没有其余辅助,因为CL帕杰罗会把公文拷贝到3个临时目录下,然后在那运营web,而CL帕杰罗只会拷贝托管文件,那正是干吗大家强烈把非托管的dll放在了bin下却依旧提醒不能加载模块了.  具体做法如下:  首先大家在服务器上随便找个地点新建八个索引,要是为C:\DLL  然后,在环境变量中,给Path变量添加那么些目录  最终,把全部的非托管文件都拷贝到C:\DLL中.  可能更索性的把DLL放到system32索引  对于能够团结配置的应用程序,那样未偿不是1个消除办法,可是,如若大家用的是杜撰空间,我们是无法把注
册PATH变量可能把大家温馨的DLL拷到system32索引的。同时大家也不肯定明白我们的Dll的大体路径。  DllImport里面只可以用字符
串常量,而不可见用Server.MapPath(@”~/Bin/Judge.dll”)来规定物理路径。ASP.NET中要选拔DllImport
的,必须在先“using
System.Runtime.InteropServices;”不过,笔者发觉,调用这种”非托管Dll”非常的慢,大概是因为本人的点子需求长途验证
吧,然则实际上是太慢了。经过一翻钻探,终于想到了三个健全的消除办法首先大家用

3.在缓解方案添加C++工程,进度略

DllImport的可选属性参数表达:
EntryPoint
        内定要调用的 DLL 入口点。 
SetLastError
      判断在实施该方法时是或不是出错(使用 马尔斯hal.GetLastWin32Error API
函数来分明)。C#中暗中同意值为
false。
CharSet
           控制名称及函数中字符串参数的编码情势。暗许值为
CharSet.Ansi。
ExactSpelling
     是不是修改入口点以对应不相同的字符编码格局。
CallingConvention
 钦命用于传递方式参数的调用约定。暗中认可值为
WinAPI。该值对应于基于3一人速龙平台的 __stdcall。
BestFitMapping
    是或不是启用一级映射功效,暗中认可为 true。最棒映射功效提供在没有匹配项时,自动提供匹配的字符。不能映射的字符平时转换为私下认可的“?”。

“每2个lib文件正是多少函数(要是唯有函数)的定义”
lib库有三种,一种是含有了函数所在DLL文件和文书中等高校函授数地方的新闻,称为导出库;一种是包涵函数代码本人,一般现有的DLL,用的是前一种库;在此以前在DOS下的TC/BC等,是后一种库。包蕴函数原型证明的,是头文件(.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(不应转换签名)。并且重返值有1个增大的
[out, retval] 参数的非托管签名。  

“通过#include蕴含这几个函数评释的头文件后,我们的应用程序就能够应用lib文件中的函数”

独家赢得了LoadLibrary和GetProcAddress函数的地方,再经过那三个函数来得到大家的DLL里面包车型地铁函数。
大家能够先用Server.MapPath(@”~/Bin/Judge.dll”)来取得大家的DLL的物理路径,然后再用LoadLibrary实行载入,最后用GetProcAddress取得要用的函数地址

4.新增加的C++工程,引用DLL,同时引入名字空间;

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

还要指确定人员编制写翻译器链接相应的库文件。在IDE环境下,一般是二遍内定全体应用的库文件,编写翻译器自个儿寻找每一个模块须求的库;在指令行编写翻译环境下,要求钦点每种模块调用的库。

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

  •   引用库使用 #using “xxx.dll” 那里需要制定dll的相对路径
  • #pragma managed;  // 告诉编写翻译器,将选取托管代码

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

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

“那他和向来交给那叁个函数定义的文本,比如.cpp文件,和头文件有如何界别,静态链接库有怎样用”
cpp文件是源代码,库文件是编写翻译后的二进制代码,比如您能够调用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);      
        } 
    }

 

C
C# 备注

“还有不明了的是,静态链接库中的lib文件只要利用,则整个lib文件的始末都放进了exe文件中,那它是被编写翻译进去照旧链接的时候总是进去的啊?”
是在链接的时候将lib链接到目的代码中。

上边代码实行调用

4858.com 3

short int16 短整型

静态链接库(Lib)
在VC++6.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++调用引用一样,不须求钦定特殊字符;

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(1, 2, 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
C2.0中的C库函数(我们用来的scanf、printf、memcpy、strcpy等)就来自那种静态库。

一 在C#先后设计中采纳Win32类库
常用对应品种:
① 、DWOKugaD 是 4 字节的平头,因而大家能够运用 int 或 uint 作为 C#
对应类型。
2、bool 类型与 BOOL 对应。

ref
供给参数在传递给函数前要开头化,out则不须求,常见于阳台调用中。out和ref传递的都以援引而不是值,out侧重于出口使用以前不需赋值而ref在应用从前必要赋值,别的那五个关键字能够变相完结使一个办法输出多少个值。ref能够把参数的数值传递进函数,可是out是要把参数清空,正是说你不也许把三个数值从out传递进入的,out进去后,参数的数值为空,所以您不可能不早先化2遍。这几个就是八个的区分,或然说就好像某些网络朋友说的,ref是有进有出,out是只出不进。表达是援引的传递。

上面来探望怎么采用这几个库,在libTest工程所在的工作区内new2个libCall工程。libCall工程仅包罗二个main.cpp文件,它以身作则了静态链接库的调用方法,其源代码如下:

演示一:调用 Beep() API 来发出声音
Beep() 是在 kernel32.lib 中定义的,在MSDN 中的定义,Beep具有以下原型:
BOOL Beep(DWO昂CoraD dwFreq, // 声音频率
DWO昂CoraD 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” )
 //钦赐与静态库一起再而三
int main(int argc, char* argv[])
{
     printf( “2 + 3 = %d”, add( 2, 3 ) );
}
  静态链接库的调用便是那般简单,大概大家天天都在用,可是我们从未了然这些概念。代码中#pragma
comment( lib , “..\\debug\\libTest.lib”
)的情致是指本文件生成的.obj文件应与libTest.lib一起接连

示范二:枚举类型和常量
MessageBeep() 是在 user32.lib 中定义的,在MSDN
中的定义,MessageBeep具有以下原型:
BOOL MessageBeep(UINT uType // 声音类型
4858.com,);

//命名空间


用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++生成静态库文件
前几天闲着没事做,自个儿写了有些小笔记,不明了对于新手有没用,高手就无须看了,作为新手的笔者斗胆来刊登三个笔记,正是静态库文件的包裹进程,使用VC++6.0编写,下边是本文,可能笔者的措辞并不专业

演示三:处理组织
有时自身急需显然本身台式机的电池组处境。Win32 为此提供了电源管理函数,搜索
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)
{
//a2 b2不能够更改a1 b1
//a2=..
//b2=…
return a+b;
}

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

终极链接器将大家编写翻译的相继目标文件里的机器码和静态库(标准C/C++库)中的函数机器码链接到一起形成3个扩张名为.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)
{
//能够改变 a1, b1
*a2=…
*b2=…
return a+b;
}

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

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

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 ,astr1 bstr1不会被改变
return a+b;
}

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

静态库文件如同一个库房可能容器,里面封装了有的可举办机器码.那几个机器码是我们用程序设计语言,比如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;
}

(整理,源作品来源于互联网)

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

DLL 回调函数

在VC++6.0中采用File-New-Win32 Static
Library,写好工程名制造好工作空间后再选用菜单中New-File来为工程添加C或然C++
源文件.

BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

若是大家为该工程添加了3个名为lib_c.c和1个名为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)
//该函数是1个外部函数,任何公文都足以访问它

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
//那是2个外部全局变量,任何公文能够访问它

//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”关键字修饰定义的函数或全局变量.

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

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

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

接下去就要将写好的C/C++源文件举办编写翻译和链接,最终会变卦一个恢宏名为.lib的文件.该公文正是静态库文件了,该静态库文件是无法直接运转的,大家所编写翻译的C/C++源文件的机器码就早已被打包进那一个用VC++6.0创立的静态库文件之中去了.

二.什么样将编辑好的静态库文件像使用C/C++标准库那样选择,上边将接二连三商量

1.用VC++6.0新建八个工程名为TEST,添加三个名为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”)那条指令告诉链接器到字符串所代表的路线下去找库文件,那里小编将库文件放到了脚下工程目录下.也足以不写那句.

还有一种办法,能够一贯在VC++6.0中安装依次选用tools、options、directories、library
files菜单或选取,填入库文件路径(只键入库文件所在目录路径而无法输入库文件名),那只是告诉链接器库文件所在目录的路径,还没告知链接器库文件名,方法是VC++6.0中装置依次选拔project-settings-link
在object/library modules: 那栏输入库文件名字然后就OK了

2.当用C++源文件的靶子文件和库文件的代码链接时有一点小改变,那里就不浪费口舌了,若是我们新建了3个工程并添加了1个名为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文件中摸索动态调用函数(一般为DLL中的函数)的地方音讯,此时内需在lib文件中搜寻,如搜寻SetWindowText()函数的地点偏移就供给查找user32.lib文件。(.lib也可用于静态链接的内嵌代码)

 

lib和dll文件的界别和联络    
   
 
.dll是在您的程序运维的时候才连接的公文,由此它是一种相比较小的可执行文件格式,.dll还有其余的文件格式如.ocx等,全数的.dll文件都是可进行。
 
   
 
.lib是在您的次第编译连接的时候就接连的文件,因而你无法不告知编写翻译器连接的lib文件在那边。一般的话,与动态连接文件绝相比,lib文件也被称为是静态连接库。当您把代码编写翻译成那二种格式的文件时,在随后他们就不可能再被更改。假若你想行使lib文件,就必须:
 
  1?   包罗三个一见倾心的头文件报告编写翻译器lib文件之中的具体内容  
  2?   设置lib文件允许编译器去探寻已经编写翻译好的二进制代码  
   
 
倘若你想从你的代码分离2个dll文件出来代替静态连接库,仍旧须求贰个lib文件。这一个lib文件将被连接受程序告诉操作系统在运营的时候你想用到哪边dll文件,一般景况下,lib文件里有对应的dll文件的名字和3个指明dll输出函数入口的顺序表。固然不想用lib文件或然是从未有过lib文件,能够用WIN32  
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语言中有部分函数不需求展开编写翻译,有局地函数也足以在多少个文件中利用。一般的话,这个函数都会实施一些正式职分,如数据库输入/输出操作或显示器控制等。能够预先对这个函数实行编译,然后将它们放置在局部奇异的目的代码文件中,那么些目的代码文件就称为库。库文件中的函数能够通过连接程序与应用程序进行连接。那样就无需在历次开发顺序时都对那几个通用的函数进行编写翻译了。  
 
   
 
  不相同类型的应用程序将会使用不一致的函数库。例如:libdbm库中组包括了对数据库文件进行走访的dbm函数,须要对数据库举办操作的程序就会与该库举办一而再。数学应用程序将使用数学库libm,X-Windows应用程序将应用Xlib库,libX11。此外,全部的先后都将利用正规的C函数库。libc,该库中带有了诸好内部存款和储蓄器管理或输入输出操作的中央函数,那些库都存放在/usr/lib那个类别公用的目录中,系统中的任何用户都能够行使那一个库。当然用户也得以建立和睦专用的库函数,供自己或任何钦命的人口选拔。  
 
   
 
  库能够有两种接纳的款式:静态、共享和动态。静态库的代码在编写翻译时就已再而三到开发职员开发的应用程序中,而共享库只是在程序开首运维时才载入,在编写翻译时,只是简短地钦赐必要运用的库函数。动态库则是共享库的另一种变更情势。动态库也是在程序运转时载入,但与共享库差异的是,使用的库函数不是在程序运营开端,而是在先后中的语句要求利用该函数时才载入。动态库可以在程序运转时期保释动态库所占用的内部存款和储蓄器,腾出空间供别的程序接纳。由于共享库和动态库并不曾在程序中归纳库函数的始末,只是包罗了对库函数的引用,因而代码的范围相比较小。

 

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

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

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

用法,lib需求个.lib文件和贰个.h文书,程序正常使用.h的函数,在链接选项里参与.lib文件就ok

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

发表评论

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

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有