c++调用c#写的DLL;

1,什么是dll文件?

.h头文件是编写翻译时务必的,lib是链接时需求的,dll是运营时须求的。

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

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

DLL(Dynamic Link
Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是四个整机的可执行文件,它们被划分成一些相对独立的动态链接库,即DLL文件,放置于系统中。当大家履行某贰个程序时,相应的DLL文件就会被调用。1个应用程序可应用多少个DLL文件,贰个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.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只好放置在形式注解上。
  2、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
参数提醒方法的签字应当被保存依然被撤换。当签名被转移时,它被转移为3个兼有
HRESULT 重返值和该重回值的一个名称叫 retval
的增大输出参数的签约。假使未钦点 PreserveSig,则选用暗中认可值 true。
   f、SetLastError 参数提示方法是或不是保留 Win32″上一谬误”。要是未指定SetLastError,则动用默许值 false。
  四、它是一回性属性类。
  5、别的,用 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的选拔手续及如下:

当我们在和谐的先后中援引了多个H文件里的函数,编链器怎么驾驭该调用哪个DLL文件呢?那正是LIB文件的成效:
告诉链接器
调用的函数在哪个DLL中,函数执行代码在DLL中的什么职位,这也等于干什么须求增大依赖项
.LIB文件,它起到大桥的功效。即便生成静态库文件,则尚未DLL
,唯有lib,那时函数可实施代码部分也在lib文件中

 

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

一,需求检讨选用的dll的对象平台(Any
Cpu,x捌陆,x6四),在档次属性生成选项卡中接纳与dll相呼应的靶子平台。因为托管dll是在.net的条件下转移的,转换为机器语言后能够自动识别目的平台即有框架支持解释,而非托管不可见本身辨认必要人工的设置。

当前以lib后缀的库有三种,一种为静态链接库(Static
Libary,以下简称“静态库”),另1种为动态连接库(DLL,以下简称“动态库”)的导入库(Import
Libary,以下简称“导入库”)。静态库是3个依旧八个obj文件的包装,所以有人干脆把从obj文件生成lib的进度称为Archive,即联合到共同。比如您链接三个静态库,假设内部有错,它会准确的找到是哪位obj有错,即静态lib只是壳子。动态库1般会有相应的导入库,方便程序静态载入动态链接库,不然你也许就要求自个儿LoadLibary调入DLL文件,然后再手工业GetProcAddress得到对应函数了。有了导入库,你只必要链接导入库后依据头文件函数接口的申明调用函数就足以了。导入库和静态库的区分非常大,他们精神是不雷同的东西。静态库本人就带有了实际上施行代码、符号表等等,而对于导入库而言,其实际的推行代码位于动态库中,导入库只包蕴了地址符号表等,确定保证程序找到相应函数的1部分基本地址消息。

   
DllImport
是System.Runtime.InteropServices命名空间下的一个属性类,其效果是提供从非托管DLL导出的函数的不能缺少调用音信。
    DllImport属性应用于艺术,供给最少要提供含有入口点的dll的名号。
    DllImport的定义如下:

金沙注册送58 1

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

壹般的动态库程序有lib文件和dll文件。lib文件是必须在编写翻译期就连接受应用程序中的,而dll文件是运作期才会被调用的。倘使有dll文件,那么相应的lib文件壹般是某个索引音讯,具体的落到实处在dll文件中。若是唯有lib文件,那么这么些lib文件是静态编写翻译出来的,索引和兑现都在其间。静态编写翻译的lib文件有裨益:给用户设置时就不须要再挂动态库了。但也有缺点,便是促成应用程序比较大,而且失去了动态库的面面俱圆,在本子升级时,同时要宣布新的应用程序才行。在动态库的景况下,有多个文件,而三个是引进库(.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文件:
1)、exe所在目录;
二)、System3二索引(系统目录);


用法示例:

二.改动出口路径输出为 ../bin/debug; ../bin/release 方便c++可以一定找到

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

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

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

金沙注册送58 2

DllImport的导入规则:
壹)、方法名与Win
API完全1样。假若在C#中调用时展现完全两样的点子名称,则需求引进EntryPoint属性,使用别称显示。
贰)、函数除急需DllImport类修饰符外,还亟需注明public
static extern类型。
叁)、函数重回值和参数必须和调用的API的完全等同。

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

    以上是用来写入ini文件的一个win3二api。
    
   
用此方法调用Win3二API的数据类型对应:DWORubiconD=int或uint,BOOL=bool,预约义常量=enum,结构=struct。
 

 

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

静态链接库与动态链接库都以共享代码的法子,若是采纳静态链接库,则无论你愿不愿意,lib
中的指令都全部被一向包蕴在终极生成的 EXE 文件中了。可是若选拔 DLL,该
DLL 不必被含有在最后 EXE 文件中,EXE
文件实施时能够“动态”地引用和卸载那几个与 EXE 独立的 DLL
文件。静态链接库和动态链接库的其余五个组别在于静态链接库中不可能再包括其余的动态链接库或然静态库,而在动态链接库中还是能够再包罗其余的动态或静态链接库。

DllImport会依照顺序自动去找寻的地点: 一、exe所在目录 贰、System3二目录
三、环境变量目录所以只要求您把引用的DLL 拷贝到那三个目录下
就能够不用写路径了
或然能够这么server.MapPath(.\bin\*.dll)web中的,同时也是应用程序中的
后来发现用[DllImport(@”C:\OJ\Bin\Judge.dll”)]如此那般钦命DLL的绝对路径就可以不奇怪装载。 那几个难题最常出现在采取第3方非托管DLL组件的时候,小编的也壹样是此时出的题材,Asp.Net
Team的法定消除方案如下: 首先需求承认你引用了什么组件,那么些是托管的,哪些是非托管的.托管的很好办,直接被运用的急需引用,直接使用的急需拷贝
到bin目录下.非托管的处理会相比较麻烦.实际上,你拷贝到bin未有此外救助,因为CLLAND会把文件拷贝到3个临时目录下,然后在那运转web,而CL汉兰达只会拷贝托管文件,那正是为何大家肯定把非托管的dll放在了bin下却还是提醒不能够加载模块了.  具体做法如下:  首先大家在服务器上随便找个地点新建多少个目录,假若为C:\DLL  然后,在环境变量中,给Path变量添加那一个目录  最终,把全体的非托管文件都拷贝到C:\DLL中.  或然更索性的把DLL放到system3二目录  对于能够友善安插的应用程序,那样未偿不是3个化解办法,然则,如若大家用的是虚拟空间,大家是不能够把注
册PATH变量恐怕把我们温馨的DLL拷到system3贰目录的。同时大家也不必然知道我们的Dll的物理路径。  DllImport里面只可以用字符
串常量,而不可见用Server.MapPath(@”~/Bin/Judge.dll”)来分明物理路径。ASP.NET中要选择DllImport
的,必须在先“using
System.Runtime.InteropServices;”不过,作者发觉,调用那种”非托管Dll”十分的快,恐怕是因为本身的方法须要中远距离验证
吧,但是事实上是太慢了。经过1翻切磋,终于想到了几个圆满的消除办法首先大家用

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

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

“每1个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(不应转换签名)。并且再次回到值有贰个叠加的
[out, retval] 参数的非托管签名。  

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

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

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

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

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

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

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

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

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

“那她和直接提交这3个函数定义的公文,比如.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链接到指标代码中。

上面代码举办调用

金沙注册送58 3

条件下利用动态链接库dll的详解,之间的关系和成效的界别。short int16 短整型

静态链接库(Lib)
在VC++6.0中new1个名叫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函数

伍.使用类库

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

  编写翻译这些工程就得到了贰个.lib文件,那个文件正是2个函数库,它提供了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#程序设计中使用Win3二类库
常用对应项目:
一、DWO福特ExplorerD 是 4 字节的平头,由此大家得以行使 int 或 uint 作为 C#
对应类型。
2、bool 类型与 BOOL 对应。

ref
供给参数在传递给函数前要初步化,out则不必要,常见于阳台调用中。out和ref传递的都以引用而不是值,out侧重于出口使用在此之前不需赋值而ref在运用从前须求赋值,别的这多个根本字能够变相完结使三个办法输出八个值。ref能够把参数的数值传递进函数,不过out是要把参数清空,正是说你不只怕把1个数值从out传递进入的,out进去后,参数的数值为空,所以您无法不初步化三遍。那一个正是八个的区分,也许说就如一些网民说的,ref是有进有出,out是只出不进。表明是引用的传递。

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

以身作则一:调用 Beep() API 来发出声音
Beep() 是在 kernel32.lib 中定义的,在MSDN 中的定义,Beep具有以下原型:
BOOL Beep(DWO宝马7系D 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.lib壹起一而再

示范贰:枚举类型和常量
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 参数实际上接受1组预先定义的常量,对于 uType 参数,使用 enum
类型是合乎情理的。
[DllImport(“user32.dll”)]
public static extern bool MessageBeep(BeepType beepType);

using
System.Runtime.InteropServices;

用VC++生成静态库文件
后天闲着没事做,本身写了某个小笔记,不晓得对于新手有没用,高手就毫无看了,作为新手的笔者斗胆来揭橥四个笔记,就是静态库文件的卷入进度,使用VC++陆.0编写,上面是本文,只怕笔者的用语并不伦不类

以身作则叁:处理组织
有时候笔者急需分明自己笔记本的电池情况。Win32 为此提供了电源管理函数,搜索
MSDN 能够找到GetSystemPowerStatus() 函数。
BOOL GetSystemPowerStatus(
  LPSYSTEM_POWER_STATUS lpSystemPowerStatus
);
此函数包括指向某些协会的指针,大家从没对此进行过处理。要处理组织,大家须要用
C# 定义结构。大家从非托管的定义初阶:
typedef struct _SYSTEM_POWER_STATUS {
金沙注册送58,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文件).

以身作则4:处理字符串

//分配的库处理和接二连三到数控钦定的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不能更改a1 b1
//a2=..
//b2=…
return a+b;
}

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

谈到底链接器将我们编写翻译的逐一指标文件里的机器码和静态库(标准C/C++库)中的函数机器码链接到1起形成二个扩充名称叫.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一, b一
*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 ,astr一 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;
}

(整理,源作品来源于网络)

一.上边将研讨将C/C++源文件编译并链接成三个静态库文件的历程,

DLL 回调函数

在VC++陆.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
//那是1个表面全局变量,任何公文能够访问它

//lib_cpp.cpp中的内容

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

{
    return x-y;

}

extern “C” int data_cpp=2;

专注以下几点

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

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

(二)当”static”关键字修饰在函数或全局变量的概念中时,表示该函数或全局变量只好由本文件中加了”static”关键字修饰的函数表明或全局变量注脚来引用.

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

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

接下去就要将写好的C/C++源文件实行编译和链接,最终会转变三个扩充名字为.lib的文件.该文件正是静态库文件了,该静态库文件是无法向来运营的,大家所编写翻译的C/C++源文件的机器码就已经棉被服装进进这么些用VC++陆.0创造的静态库文件之中去了.

二.怎么将编辑好的静态库文件像使用C/C++标准库那样选择,上面将继续商讨

一.用VC++陆.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”)那条指令告诉链接器到字符串所表示的途径下去找库文件,那里小编将库文件放到了现阶段工程目录下.也能够不写那句.

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

贰.当用C++源文件的对象文件和库文件的代码链接时有一点小改变,那里就不浪费口舌了,假如我们新建了三个工程并添加了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()函数等,必要在user3贰.dll中找到该函数。DLL能够简简单单认为是一种含有供外人调用的函数和能源的可执行文件。

.lib用于链接阶段,在链接各部分目的文件(平日为.obj)到可执行文件(平日为.exe)进程中,须要在.lib文件中检索动态调用函数(1般为DLL中的函数)的地方音讯,此时须要在lib文件中找寻,如搜寻SetWindowText()函数的地方偏移就须求查找user3贰.lib文件。(.lib也可用来静态链接的内嵌代码)

 

lib和dll文件的界别和关联    
   
 
.dll是在您的程序运维的时候才连接的文件,因而它是1种比较小的可执行文件格式,.dll还有此外的文件格式如.ocx等,全部的.dll文件都以可进行。
 
   
 
.lib是在您的主次编写翻译连接的时候就一而再的文书,因而你必须告知编写翻译器连接的lib文件在那边。一般的话,与动态连接文件相对照,lib文件也被称之为是静态连接库。当你把代码编写翻译成那二种格式的文本时,在其后他们就不也许再被转移。就算你想使用lib文件,就亟须:
 
  一?   包罗三个应和的头文件报告编写翻译器lib文件之中的具体内容  
  二?   设置lib文件允许编写翻译器去寻觅已经编写翻译好的贰进制代码  
   
 
假设你想从您的代码分离一个dll文件出来代替静态连接库,如故须要三个lib文件。这么些lib文件将被连接受程序告诉操作系统在运作的时候你想用到什么dll文件,壹般景况下,lib文件里有照应的dll文件的名字和3个指明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般的话,这个函数都会履行1些正式任务,如数据库输入/输出操作或屏幕控制等。可以优先对那几个函数举办编写翻译,然后将它们放置在部分非正规的对象代码文件中,那些指标代码文件就称为库。库文件中的函数能够透过连日程序与应用程序进行接二连三。那样就不必在历次开发顺序时都对那么些通用的函数进行编写翻译了。  
 
   
 
  分歧门类的应用程序将会动用不一致的函数库。例如:libdbm库中组包蕴了对数据库文件进行访问的dbm函数,须求对数据库实行操作的主次就会与该库举行连接。数学应用程序将应用数学库libm,X-Windows应用程序将利用Xlib库,libX1壹。其它,全体的程序都将接纳标准的C函数库。libc,该库中隐含了诸好内部存款和储蓄器管理或输入输出操作的主导函数,那一个库都存放在/usr/lib这么些种类公用的目录中,系统中的任何用户都能够使用那几个库。当然用户也能够创设友好专用的库函数,供自身或任何钦定的人口接纳。  
 
   
 
  库能够有三种选择的样式:静态、共享和动态。静态库的代码在编写翻译时就已三番五次到开发人士开发的应用程序中,而共享库只是在程序起始运维时才载入,在编写翻译时,只是简短地钦定必要选择的库函数。动态库则是共享库的另1种变化方式。动态库也是在程序运营时载入,但与共享库区别的是,使用的库函数不是在程序运转初阶,而是在程序中的语句必要运用该函数时才载入。动态库能够在程序运营时期保释动态库所占据的内部存储器,腾出空间供别的程序接纳。由于共享库和动态库并从未在先后中包涵库函数的内容,只是包涵了对库函数的引用,由此代码的范畴相比较小。

 

lib是静态库,dll1般是动态链接库(也有相当大可能率是别的)

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

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

用法,lib要求个.lib文件和二个.h文件,程序正常化使用.h的函数,在链接选项里参预.lib文件就ok

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

相关文章

网站地图xml地图