威尼斯人线上娱乐

【威尼斯人线上娱乐】中间的涉及和遵守的区分,环境下利用动态链接库dll的详解

12 4月 , 2019  

c++调用c#写的DLL;

1,什么是dll文件?

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

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

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

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

叠加正视项的是.lib不是.dll,若生成了DLL,则必定也生成
LIB文件。假若要到位源代码的编写翻译和链接,有头文件和lib就够了。要是也使动态连接的程序运营起来,有dll就够了(放在Debug文件夹里)。在开发和调剂阶段,当然最棒都有。

 

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

二,托管dll和非托管dll不一致是怎么着?

.h .lib .dll叁者的关联是:

大家在实质上中国人民解放军海军事工业程大学业作学习C#的时候,大概会问:为啥我们要为1些业已存在的作用(比如
Windows中的1些作用,C++中已经编写制定好的有个别措施)要重复编写代码,C#有未有措施能够直接都用那几个本来已经存在的功力吗?答案是自然的,大家能够通过C#中的DllImport直接调用这个成效。
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 再次来到值和该再次来到值的1个名叫 retval
的叠加输出参数的签字。假使未钦点 PreserveSig,则选择暗中认可值 true。
   f、SetLastError 参数提示方法是不是保留 Win32″上1谬误”。借使未内定SetLastError,则动用暗许值 false。
  4、它是1遍性属性类。
  五、别的,用 DllImport 属性修饰的法子必须持有 extern 修饰符。

不能够一举成功的难点:

托管DLL正是力所能及在公共语言运行库(Common
Language
Runtime,简称CL本田CR-V)中可见一贯引用的,并且扩大为“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,过程略;

1,须要检讨选拔的dll的目的平台(Any
Cpu,x8陆,x6④),在品种属性生成选项卡中挑选与dll相呼应的对象平台。因为托管dll是在.net的条件下转移的,转换为机器语言后能够自动识别指标平台即有框架协助解释,而非托管不可见和好分辨要求人工的安装。

近日以lib后缀的库有二种,一种为静态链接库(Static
Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import
Libary,以下简称“导入库”)。静态库是3个依旧三个obj文件的包装,所以有人干脆把从obj文件生成lib的进度称为Archive,即联合到联合。比如你链接叁个静态库,如果内部有错,它会规范的找到是哪位obj有错,即静态lib只是壳子。动态库壹般会有对应的导入库,方便程序静态载入动态链接库,不然你恐怕就须要团结LoadLibary调入DLL文件,然后再手工GetProcAddress得到对应函数了。有了导入库,你只供给链接导入库后依照头文件函数接口的扬言调用函数就能够了。导入库和静态库的区分十分的大,他们精神是不相同等的东西。静态库本人就含有了实际上执行代码、符号表等等,而对此导入库而言,其实际的施行代码位于动态库中,导入库只包蕴了地址符号表等,确认保证程序找到相应函数的有些主干地址新闻。

   
DllImport
是System.Runtime.InteropServices命名空间下的二个属性类,其功用是提供从非托管DLL导出的函数的不可或缺调用新闻。
    DllImport属性应用于方法,需要最少要提供含有入口点的dll的名目。
    DllImport的概念如下:

威尼斯人线上娱乐 1

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

壹般的动态库程序有lib文件和dll文件。lib文件是必须在编写翻译期就连接受应用程序中的,而dll文件是运营期才会被调用的。如果有dll文件,那么相应的lib文件1般是一对目录新闻,具体的贯彻在dll文件中。要是唯有lib文件,那么那个lib文件是静态编写翻译出来的,索引和实现都在在那之中。静态编写翻译的lib文件有益处:给用户安装时就不要求再挂动态库了。但也有毛病,正是促成应用程序比较大,而且失去了动态库的面面俱圆,在本子升级时,同时要揭露新的应用程序才行。在动态库的气象下,有七个文件,而3个是引入库(.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会依据以下三种顺序查找dll文件:
一)、exe所在目录;
2)、System32目录(系统目录);


用法示例:

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

叁)、环境变量目录。(即要求将dll及重视文件放到二个目录中的任何多少个索引中)。

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

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

威尼斯人线上娱乐 2

DllImport的导入规则:
一)、方法名与Win
API完全壹样。即使在C#中调用时显得完全两样的点子名称,则需求引进EntryPoint属性,使用外号呈现。
2)、函数除急需DllImport类修饰符外,还亟需申明public
static extern类型。
三)、函数再次来到值和参数必须和调用的API的通通一致。

    
静态连接库正是把(lib)文件中用到的函数代码直接链接进指标程序,程序运维的时候不再必要别的的库文件;动态链接就是把调用的函数所在文书模块(DLL)和调用函数在文书中的地方等音讯链接进指标程序,程序运维的时候再从DLL中查找对应函数代码,由此要求相应DLL文件的支持。

    以上是用来写入ini文件的八个win3二api。
    
   
用此措施调用Win32API的数据类型对应:DWO安德拉D=int或uint,BOOL=bool,预订义常量=enum,结构=struct。
 

 

四)、必须引进System.Runtime.InteropServices命名空间。

静态链接库与动态链接库都以共享代码的章程,假诺应用静态链接库,则无论你愿不愿意,lib
中的指令都全部被一直包涵在终极生成的 EXE 文件中了。可是若使用 DLL,该
DLL 不必被含有在最后 EXE 文件中,EXE
文件实施时方可“动态”地引用和卸载那几个与 EXE 独立的 DLL
文件。静态链接库和动态链接库的其余三个差别在于静态链接库中无法再包罗别的的动态链接库可能静态库,而在动态链接库中还足以再包罗其余的动态或静态链接库。

DllImport会依据顺序自动去找寻的地点: 一、exe所在目录 二、System32索引
叁、环境变量目录所以只必要你把引用的DLL 拷贝到那多个目录下
就足以不用写路径了
只怕能够如此server.Map帕特h(.\bin\*.dll)web中的,同时也是应用程序中的
后来发现用[DllImport(@”C:\OJ\Bin\Judge.dll”)]如此钦命DLL的相对路径就能够符合规律装载。 那个题材最常现身在应用
第1方非托管DLL组件的时候,作者的也壹如既往是此时出的难点,Asp.Net
Team的官方化解方案如下: 首先供给认同你引用了怎么样组件,那1个是托管的,哪些是非托管的.托管的很好办,直接被利用的内需引用,直接使用的须要拷贝
到bin目录下.非托管的处理会相比麻烦.实际上,你拷贝到bin未有任何辅助,因为CL奥迪Q7会把公文拷贝到2个临时目录下,然后在那运营web,而CL奥德赛只会拷贝托管文件,那就是干吗大家明白把非托管的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.GetLastWin32Error API
函数来分明)。C#中暗中同意值为
false。
CharSet
           控制名称及函数中字符串参数的编码情势。默许值为
CharSet.Ansi。
ExactSpelling
     是或不是修改入口点以对应差异的字符编码格局。
CallingConvention
 钦点用于传递方式参数的调用约定。私下认可值为
WinAPI。该值对应于基于三十二位速龙平台的 __stdcall。
BestFitMapping
    是或不是启用顶级映射功用,暗中认可为 true。最好映射成效提供在并未有相配项时,自动提供匹配的字符。不大概映射的字符常常转换为暗中认可的“?”。

“每一个lib文件正是多少函数(即便只有函数)的概念”
lib库有三种,壹种是包罗了函数所在DLL文件和文件中等高校函授数地点的音信,称为导出库;一种是含有函数代码本人,1般现有的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(不应转换签名)。并且再次来到值有3个附加的
[out, retval] 参数的非托管签名。  

【威尼斯人线上娱乐】中间的涉及和遵守的区分,环境下利用动态链接库dll的详解。“通过#include包蕴这个函数注解的头文件后,我们的应用程序就能够采用lib文件中的函数”

个别得到了LoadLibrary和GetProcAddress函数的地址,再经过那八个函数来获得大家的DLL里面的函数。
我们能够先用Server.MapPath(@”~/Bin/Judge.dll”)来获得大家的DLL的情理路径,然后再用LoadLibrary举办载入,最终用GetProcAddress取得要用的函数地址

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

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

还要钦定编写翻译器链接相应的库文件。在IDE环境下,壹般是1遍内定全体应用的库文件,编写翻译器本身摸索每一种模块需求的库;在指令行编写翻译环境下,要求钦赐每种模块调用的库。

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

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

  • using namespace CsDll00二;  // 引进名字空间

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

“那她和直接交给那多少个函数定义的文书,比如.cpp文件,和头文件有何样界别,静态链接库有怎么着用”
cpp文件是源代码,库文件是编写翻译后的贰进制代码,比如你能够调用Windows的API,不过无法看到其源代码1样。

 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链接到目的代码中。

上边代码进行调用

威尼斯人线上娱乐 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++调用引用一样,不供给钦定特殊字符;

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 指针

  编译那几个工程就获取了1个.lib文本,这几个文件就是3个函数库,它提供了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类库
常用对应品种:
一、DWO汉兰达D 是 四 字节的平头,因而大家得以采用 int 或 uint 作为 C#
对应类型。
2、bool 类型与 BOOL 对应。

ref
供给参数在传递给函数前要开头化,out则不须要,常见于阳台调用中。out和ref传递的都是援引而不是值,out侧重于出口使用在此之前不需赋值而ref在行使以前供给赋值,别的那三个关键字能够变相达成使三个艺术输出七个值。ref能够把参数的数值传递进函数,可是out是要把参数清空,正是说你不或然把四个数值从out传递进入的,out进去后,参数的数值为空,所以你无法不发轫化三遍。那一个正是三个的界别,或许说就好像有的网上朋友说的,ref是有进有出,out是只出不进。表达是援引的传递。

下边来看看怎么选择那个库,在libTest工程所在的工作区内new3个libCall工程。libCall工程仅包涵1个main.cpp文件,它以身作则了静态链接库的调用方法,其源代码如下:

演示一:调用 Beep() API 来发出声音
Beep() 是在 kernel3二.lib 中定义的,在MSDN 中的定义,Beep具有以下原型:
BOOL Beep(DWOPRADOD 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” )
 //内定与静态库一起三番五次
int main(int argc, char* argv[])
{
     printf( “2 + 3 = %d”, add( 2, 3 ) );
}
  静态链接库的调用便是那般容易,或者大家天天都在用,可是大家向来不清楚这几个定义。代码中#pragma
comment( lib , “..\\debug\\libTest.lib”
)的意味是指本文件生成的.obj文件应与libTest.lib1起接连

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

//命名空间


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

using
System.Runtime.InteropServices;

用VC++生成静态库文件
今日闲着没事做,本身写了壹些小笔记,不精晓对于新手有没用,高手就无须看了,作为新手的笔者斗胆来刊登3个笔记,正是静态库文件的卷入进度,使用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++静态库文件中的.即那2个扩充名字为.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贰 b二不能够更改a一 b1
//a2=..
//b2=…
return a+b;
}

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

最后链接器将我们编写翻译的逐一指标文件里的机器码和静态库(标准C/C++库)中的函数机器码链接到一起形成二个恢宏名叫.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++源文件编写翻译链接成贰个静态库文件,但它不是可进行模块,它体内含有可实施机器码

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 二 ,astr1 bstr壹不会被改动
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;
}

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

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

DLL 回调函数

在VC++陆.0中挑选File-New-Win3二 Static
Library,写好工程名创设好干活空间后再选择菜单中New-File来为工程添加C恐怕C++
源文件.

BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

只要大家为该工程添加了二个名叫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)
//该函数是2个外表函数,任何公文都得以访问它

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++标准库那样采纳,下面将三番五次研讨

1.用VC++6.0新建1个工程名称叫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++陆.0中安装依次选取tools、options、directories、library
files菜单或选取,填入库文件路径(只键入库文件所在目录路径而无法输入库文件名),那只是告诉链接器库文件所在目录的路线,还没告知链接器库文件名,方法是VC++6.0中设置依次接纳project-settings-link
在object/library modules: 那栏输入库文件名字然后就OK了

贰.当用C++源文件的对象文件和库文件的代码链接时有一点小改变,那里就不浪费口舌了,假诺大家新建了三个工程并添加了3个名称为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能够简简单单认为是1种含有供外人调用的函数和财富的可执行文件。

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

 

lib和dll文件的区分和关联    
   
 
.dll是在你的程序运维的时候才连接的文书,由此它是一种相比小的可执行文件格式,.dll还有其它的文件格式如.ocx等,全部的.dll文件都以可实施。
 
   
 
.lib是在你的顺序编写翻译连接的时候就三番五次的文书,因而你必须告知编写翻译器连接的lib文件在那边。1般的话,与动态连接文件绝相比较,lib文件也被称作是静态连接库。当您把代码编写翻译成那两种格式的文书时,在后来他们就不容许再被改成。假使您想选择lib文件,就亟须:
 
  一?   包罗贰个一面如旧的头文件报告编写翻译器lib文件之中的具体内容  
  2?   设置lib文件允许编写翻译器去探寻已经编写翻译好的2进制代码  
   
 
如若你想从你的代码分离3个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文件到工程里,关键是1旦在C++工程里用了C语言写的lib文件,就必供给这么含有:
 
  extern   “C”  
  {  
  #include   “myheader.h”  
  }  
 
那是因为C语言写的lib文件没有C++所必须的名字破坏,C函数不能够被重载,因而连接器会出错。

 

C语言中有壹对函数不要求开始展览编译,有壹对函数也足以在多少个公文中应用。壹般的话,这个函数都会执行1些正式职务,如数据库输入/输出操作或显示屏控制等。能够预先对那么些函数进行编写翻译,然后将它们放置在局地分外的对象代码文件中,那么些目的代码文件就称为库。库文件中的函数能够由此连日程序与应用程序进行一而再。这样就不必在每一次开发顺序时都对那几个通用的函数实行编译了。  
 
   
 
  不一致门类的应用程序将会动用分化的函数库。例如:libdbm库中组包蕴了对数据库文件实行走访的dbm函数,需求对数据库实行操作的程序就会与该库进行一连。数学应用程序将使用数学库libm,X-Windows应用程序将应用Xlib库,libX1一。别的,全体的先后都将利用标准的C函数库。libc,该库中带有了诸好内部存款和储蓄器管理或输入输出操作的宗旨函数,这几个库都存放在/usr/lib那个种类公用的目录中,系统中的任何用户都足以运用那么些库。当然用户也能够创造协调专用的库函数,供本身或别的钦点的人士采用。  
 
   
 
  库能够有三种接纳的款型:静态、共享和动态。静态库的代码在编写翻译时就已一连到开发人士开发的应用程序中,而共享库只是在先后开端运营时才载入,在编写翻译时,只是简单地钦命必要利用的库函数。动态库则是共享库的另壹种转移方式。动态库也是在程序运营时载入,但与共享库不相同的是,使用的库函数不是在程序运转起始,而是在程序中的语句必要动用该函数时才载入。动态库能够在程序运营时期保释动态库所占有的内存,腾出空间供别的程序行使。由于共享库和动态库并不曾在先后中总结库函数的始末,只是包蕴了对库函数的引用,由此代码的框框相比小。

 

lib是静态库,dll1般是动态链接库(也有相当大希望是其余)

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

而dll是不被编译进去,是运转的时候才调入的(或然是exe刚运营就调入,也大概运营了十一分之伍才调入)

用法,lib要求个.lib文件和三个.h文书,程序通常使用.h的函数,在链接选项里出席.lib文件就ok

dll用法有2种,壹是 .h + .lib +
.dll的,用法和前边一样,中间的lib是个换车,运维的时候会调用dll
贰是:直接用dll,必要精晓dll的函数定义,用LoadLibrary和GetProcAddress把函数指针取出来,看msdn的事例吗


相关文章

发表评论

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

网站地图xml地图