-
c 如何调用lib
- 时间:2024-11-23 14:43:12
大家好,今天Win10系统之家小编给大家分享「c 如何调用lib」的知识,如果能碰巧解决你现在面临的问题,记得收藏本站或分享给你的好友们哟~,现在开始吧!
1.C++怎么调用lib库啊?
1 LIB文件直接加入到工程文件列表中
在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中"Add Files to Project"菜单,在弹出的文件对话框中选中要加入DLL的LIB文件。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
2 设置工程的 Project Settings来加载DLL的LIB文件
打开工程的 Project Settings菜单,选中Link,然后在Object/library modules下的文本框中输入DLL的LIB文件,如you.lib(或者lib文件的路径,包括文件名)。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
3 通过程序代码的方式
加入预编译指令#pragma comment (lib,"*.lib"),这种方法优点是可以利用条件预编译指令链接不同版本的LIB文件。因为,在Debug方式下,产生的LIB文件是Debug版本,如Regd.lib;在Release方式下,产生的LIB文件是Release版本,如Regr.lib。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
当应用程序对DLL的LIB文件加载后,还需要把DLL对应的头文件(*.h)包含到其中,在这个头文件中给出了DLL中定义的函数原型,然后声明
2.C++ 如何加载lib
1.lib文件的加载
lib其实就是window下的静态库文件
C++加载静态库文件只能静态加载,在编译的时候进行
下面以vs2010为例:
首先右键单击项目,选择属性:
打开配置属性-链接器-常规-附加库目录
新建一行,填入你要加载lib文件所在的路径
现在设置好了加载的lib目录,再设置要加载的lib
打开项目属性-链接器-输入-附加依赖项
在编辑框输入lib的全名(不带路径)一个文件占一行
现在再编译文件的时候,自动就会使用lib中包含的符号了
2.lib文件的使用
lib文件是window的静态库文件,其实就是很多编译好的函数代码的集合。这种文件里面的代码无法直接执行,必须进行二次编译后才能使用。当你使用了lib中的函数后,编译器会将其代码从lib文件中提取出来,然后追加到你自己的程序中去。所以,使用lib编译出来的执行程序比用dll的大一些,甚至很多。但是这样做,程序的执行效率会高很多(dll必须在运行时去找函数来执行,并且要进行耗时的长跳转),一种典型的通过空间换时间的策略。
3.C++ 调用lib 和 dll的 方法 及 动态库DLL与静态库lib的区别
可以得。将c++的lib库修改为dll,然后可以被c#调用。
下面说说c#调用dll的注意点
首先,您需要了解什么是托管,什么是非托管。一般可以认为:非托管代码主要是基于win
32平台开发的dll,activex的组件,托管代码是基于.net平台开发的。
(一) 调用dll中的非托管函数一般方法
首先,应该在c#语言源程序中声明外部方法,其基本形式是:
[dllimport(“dll文件”)] 修饰符 extern 返回变量类型 方法名称 (参数列表)
其中:
dll文件:包含定义外部方法的库文件。
修饰符: 访问修饰符,除了abstract以外在声明方法时可以使用的修饰符。
返回变量类型:在dll文件中你需调用方法的返回变量类型。
方法名称:在dll文件中你需调用方法的名称。
参数列表:在dll文件中你需调用方法的列表。
注意:需要在程序声明中使用system.runtime.interopservices命名空间。
dllimport只能放置在方法声明上。
dll文件必须位于程序当前目录或系统定义的查询路径中(即:系统环境变量中path所设置的路径)。
返回变量类型、方法名称、参数列表一定要与dll文件中的定义相一致。
若要使用其它函数名,可以使用entrypoint属性设置,如:
[dllimport("user32.dll", entrypoint="messageboxa")]
static extern int msgbox(int hwnd, string msg, string caption, int type);
其它可选的 dllimportattribute 属性:
charset 指示用在入口点中的字符集,如:charset=utf-8.ansi;
setlasterror 指示方法是否保留 win32"上一错误",如:setlasterror=true;
exactspelling 指示 entrypoint 是否必须与指示的入口点的拼写完全匹配,如:exactspelling=false;
preservesig指示方法的签名应当被保留还是被转换, 如:preservesig=true;
callingconvention指示入口点的调用约定, 如:callingconvention=callingconvention.winapi;
此外,关于“数据封送处理”及“封送数字和逻辑标量”请参阅其它一些文章。
c#操作举例:
1. 启动vs.net,新建一个项目,项目名称为“tzb”,模板为“windows 应用程序”;
2. 在“工具箱”的“ windows 窗体”项中双击“button”项,向“form1”窗体中添加一个按钮;
3. 改变按钮的属性:name为 “b1”,text为 “用dllimport调用dll弹出提示框”,并将按钮b1调整到适当大小,移到适当位置;
4. 在类视图中双击“form1”,打开“form1.cs”代码视图,在“namespace tzb”上面输入“using system.runtime.interopservices;”,以导入该命名空间;
5. 在“form1.cs[设计]”视图中双击按钮b1,在“b1_click”方法上面使用关键字 static 和
extern 声明方法“msgbox”,将 dllimport 属性附加到该方法,这里我们要使用的是“user32.dll”中的“messageboxa”函数,具体代码如下:
[dllimport("user32.dll", entrypoint="messageboxa")]
static extern int msgbox(int hwnd, string msg, string caption, int type);
然后在“b1_click”方法体内添加如下代码,以调用方法“msgbox”:
msgbox(0," 这就是用 dllimport 调用 dll 弹出的提示框哦! "," 挑战杯 ",0x30);
6. 按“f5”运行该程序,并点击按钮b1即可。
(二) 动态装载、调用dll中的非托管函数
在上面已经说明了如何用dllimport调用dll中的非托管函数,但是这个是全局的函数,假若dll中的非托管函数有一个静态变量s,每次调用这个函数的时候,静态变量s就自动加1。结果,当需要重新计数时,就不能得出想要的结果。
下面将用例子说明:
1. dll的创建
1) 启动visual c++ 6.0;
2) 新建一个“win32 dynamic-link library”工程,工程名称为“count”;
3) 在“dll kind”选择界面中选择“a simple dll project”;
4) 打开count.cpp,添加如下代码:
// 导出函数,使用“ _stdcall ” 标准调用
extern "c" _declspec(dllexport)int _stdcall count(int init);
int _stdcall count(int init)
{//count 函数,使用参数 init 初始化静态的整形变量 s ,并使 s 自加 1 后返回该值
static int s=init;
s++;
return s;
}
5) 按“f7”进行编译,得到count.dll(在工程目录下的debug文件夹中)。
2. 用dllimport调用dll中的count函数
1) 打开项目“tzb”,向“form1”窗体中添加一个按钮。
2) 改变按钮的属性:name为 “b2”,text为 “用dllimport调用dll中count函数”,并将按钮b1调整到适当大小,移到适当位置。
3) 打开“form1.cs”代码视图,使用关键字 static 和 extern 声明方法“count”,并使其具有来自 count.dll 的导出函数count的实现,代码如下:
[dllimport("count.dll")]
static extern int count(int init);
4) 在“form1.cs[设计]”视图中双击按钮b2,在“b2_click”方法体内添加如下代码:
messagebox.show(" 用 dllimport 调用 dll 中的 count 函数, n 传入的实参为 0 ,得到的结果是: "+count(0).tostring()," 挑战杯 ");
messagebox.show(" 用 dllimport 调用 dll 中的 count 函数, n 传入的实参为 10 ,得到的结果是: "+count(10).tostring()+"n 结果可不是想要的 11 哦!!! "," 挑战杯 ");
messagebox.show(" 所得结果表明: n 用 dllimport 调用 dll 中的非托管 n 函数是全局的、静态的函数!!! "," 挑战杯 ");
5) 把count.dll复制到项目“tzb”的bindebug文件夹中,按“f5”运行该程序,并点击按钮b2,便弹出如下三个提示框。
第1个提示框显示的是调用“count(0)”的结果,第2个提示框显示的是调用“count(10)”的结果,由所得结果可以证明“用dllimport调用dll中的非托管函数是全局的、静态的函数”。所以,有时候并不能达到我们目的,因此我们需要使用下面所介绍的方法:c#动态调用
dll中的函数。
3. c#动态调用dll中的函数
因为c#中使用dllimport是不能像动态load/unload assembly那样,所以只能借助api函数了。在kernel32.dll中,与动态库调用有关的函数包括[3]:
1) loadlibrary(或mfc 的afxloadlibrary),装载动态库;
2) getprocaddress,获取要引入的函数,将符号名或标识号转换为dll内部地址;
3) freelibrary(或mfc的afxfreelibrary),释放动态链接库。
它们的原型分别是:
hmodule loadlibrary(lpctstr lpfilename);
farproc getprocaddress(hmodule hmodule, lpcwstr lpprocname);
bool freelibrary(hmodule hmodule);
现在,我们可以用intptr hmodule=loadlibrary(“count.dll”);来获得dll的句柄,用intptr farproc=getprocaddress(hmodule,”_count@4”);来获得函数的入口地址。
但是,知道函数的入口地址后,怎样调用这个函数呢?因为在c#中是没有函数指针的,没有像c++那样的函数指针调用方式来调用函数,所以我们得借助其它方法。经过研究,发现我们可以通过结合使用system.reflection.emit及system.reflection.assembly里的类和函数达到我们的目的。为了以后使用方便及实现代码的复用,我们可以编写一个类。
1. 打开项目“tzb”,打开类视图,右击“tzb”,选择“添加”-->“类”,类名设置为“dld”,即dynamic loading dll 的每个单词的开头字母;
2. 添加所需的命名空间及声明参数传递方式枚举:
using system.runtime.interopservices; // 用 dllimport 需用此 命名空间
using system.reflection; // 使用 assembly 类需用此 命名空间
using system.reflection.emit; // 使用 ilgenerator 需用此 命名空间
在“public class dld”上面添加如下代码声明参数传递方式枚举:
///
/// 参数传递方式枚举 ,byvalue 表示值传递 ,byref 表示址传递
///
public enum modepass
{
byvalue = 0x0001,
byref = 0x0002
}
3. 声明loadlibrary、getprocaddress、freelibrary及私有变量hmodule和farproc:
///
/// 原型是 :hmodule loadlibrary(lpctstr lpfilename);
///
/// dll 文件名
/// 函数库模块的句柄
[dllimport("kernel32.dll")]
static extern intptr loadlibrary(string lpfilename);
///
/// 原型是 : farproc getprocaddress(hmodule hmodule, lpcwstr lpprocname);
///
/// 包含需调用函数的函数库模块的句柄
/// 调用函数的名称
/// 函数指针
[dllimport("kernel32.dll")]
static extern intptr getprocaddress(intptr hmodule, string lpprocname);
///
/// 原型是 : bool freelibrary(hmodule hmodule);
///
/// 需释放的函数库模块的句柄
/// 是否已释放指定的 dll
[dllimport("kernel32",entrypoint="freelibrary",setlasterror=true)]
static extern bool freelibrary(intptr hmodule);
///
/// loadlibrary 返回的函数库模块的句柄
///
private intptr hmodule=intptr.zero;
///
/// getprocaddress 返回的函数指针
///
private intptr farproc=intptr.zero;
4. 添加loaddll方法,并为了调用时方便,重载了这个方法:
///
/// 装载 dll
///
/// dll 文件名
public void loaddll(string lpfilename)
{
hmodule=loadlibrary(lpfilename);
if(hmodule==intptr.zero)
throw(new exception(" 没有找到 :"+lpfilename+"." ));
}
若已有已装载dll的句柄,可以使用loaddll方法的第二个版本:
public void loaddll(intptr hmodule)
{
if(hmodule==intptr.zero)
throw(new exception(" 所传入的函数库模块的句柄 hmodule 为空 ." ));
hmodule=hmodule;
}
5. 添加loadfun方法,并为了调用时方便,也重载了这个方法,方法的具体代码及注释如下:
///
/// 获得函数指针
///
/// 调用函数的名称
public void loadfun(string lpprocname)
{ // 若函数库模块的句柄为空,则抛出异常
if(hmodule==intptr.zero)
throw(new exception(" 函数库模块的句柄为空 , 请确保已进行 loaddll 操作 !"));
// 取得函数指针
farproc = getprocaddress(hmodule,lpprocname);
// 若函数指针,则抛出异常
if(farproc==intptr.zero)
throw(new exception(" 没有找到 :"+lpprocname+" 这个函数的入口点 "));
}
///
/// 获得函数指针
///
/// 包含需调用函数的 dll 文件名
/// 调用函数的名称
public void loadfun(string lpfilename,string lpprocname)
{ // 取得函数库模块的句柄
hmodule=loadlibrary(lpfilename);
// 若函数库模块的句柄为空,则抛出异常
if(hmodule==intptr.zero)
throw(new exception(" 没有找到 :"+lpfilename+"." ));
// 取得函数指针
farproc = getprocaddress(hmodule,lpprocname);
// 若函数指针,则抛出异常
if(farproc==intptr.zero)
throw(new exception(" 没有找到 :"+lpprocname+" 这个函数的入口点 "));
}
6. 添加unloaddll及invoke方法,invoke方法也进行了重载:
///
/// 卸载 dll
///
public void unloaddll()
{
freelibrary(hmodule);
hmodule=intptr.zero;
farproc=intptr.zero;
}
4.C#如何调用c++静态库(lib)
一: 隐式的加载时链接,有三种方法
1 LIB文件直接加入到工程文件列表中
在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中"Add Files to Project"菜单,在弹出的文件对话框中选中要加入DLL的LIB文件。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
2 设置工程的 Project Settings来加载DLL的LIB文件
打开工程的 Project Settings菜单,选中Link,然后在Object/library modules下的文本框中输入DLL的LIB文件,如you.lib(或者lib文件的路径,包括文件名)。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
3 通过程序代码的方式
加入预编译指令#pragma comment (lib,"*.lib"),这种方法优点是可以利用条件预编译指令链接不同版本的LIB文件。因为,在Debug方式下,产生的LIB文件是Debug版本,如Regd.lib;在Release方式下,产生的LIB文件是Release版本,如Regr.lib。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
当应用程序对DLL的LIB文件加载后,还需要把DLL对应的头文件(*.h)包含到其中,在这个头文件中给出了DLL中定义的函数原型,然后声明
二, 显式的运行时链接 ,(我用的是此方法)
隐式链接虽然实现较简单,但除了必须的*.dll文件外还需要DLL的*.h文件和*.lib文件,在那些只提供*.dll文件的场合就无法使用,而只能采用显式链接的方式。这种方式通过调用API函数来完成对DLL的加载与卸载,能更加有效地使用内存,在编写大型应用程序时往往采用此方式。这种方法编程具体实现步骤如下:
①使用Windows API函数Load Library或者MFC提供的AfxLoadLibrary将DLL模块映像到进程的内存空间,对DLL模块进行动态加载。
②使用GetProcAddress函数得到要调用DLL中的函数的指针。
③不用DLL时,用Free Library函数或者AfxFreeLibrary函数从进程的地址空间显式卸载DLL。
例:在应用程序中调用dll文件
——在应用程序中要首先装入dll后才能调用导出表中的函数,例如用mfc
创建基于对话框的工程test,并在对话框上放置"load"按钮,先添加装载代码。
1.首先在testdlg.cpp的首部添加变量设置代码:
//设置全局变量glibsample用于存储dll句柄
HINSTANCE glibsample=null; //如果定义成HANDLE类型,则出错
//第二个变量showme是指向dll
库中showme()函数的指针
typedef int(* Showme)(void);
Showme showme;
2.利用classwizard为"load"按钮添加装载dll的代码
void ctestdlg::onloadbutton()
{
//要添加的代码如下
if(glibsample!=NULL)
{
AfxMessageBox("the sample.dll has already been load.");
return;
}
//装载sample.dll,未加路径,将在三个默认路径中寻找 (1)windows的系统目录:\windows\system;
//(2)dos中path所指出的任何目录;
//(3)程序所在的目录;
glibsample=Loadlibrary("sample.dll");
//返回dll中showme()函数的地址
showme=(Showme)GetProcAddress(glibsample,"showme");
静态链接库LIB和动态链接库DLL的区别
1.什么是静态连接库,什么是动态链接库
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接 库。静态链接库与静态链接库调用规则总体比较如下。
对于静态链接库(比较简单):
首先,静态链接库的使用需要库的开发者提供生成库的.h头文件和.lib文件。
生成库的.h头文件中的声明格式如下:
extern "C" 函数返回类型 函数名(参数表);
在调用程序的.cpp源代码文件中如下:
#include "..\lib.h"
#pragma comment(lib,"..\\debug\\libTest.lib")
//指定与静态库一起链接
第二,因为静态链接库是将全部指令都包含入调用程序生成的EXE文件中。因此如果用的是静态链接库,那么也就不存在“导出某个函数提供给用户使用”的情况,要想用就得全要!要不就都别要!:)
对于动态链接库:
动态链接库的使用需要库的开发者提供生成的.lib文件和.dll文件。或者只提供dll文件。
首先我们必须先注意到DLL内的函数分为两种:
(1)DLL 导出函数,可供应用程序调用;
(2)DLL 内部函数,只能在 DLL 程序使用,应用程序无法调用它们。
因此调用程序若想调用DLL中的某个函数就要以某种形式或方式指明它到底想调用哪一个函数。
以上就是关于「c 如何调用lib」的全部内容,本文讲解到这里啦,希望对大家有所帮助。如果你还想了解更多这方面的信息,记得收藏关注本站~
Win10系统之家www.ghoSt580.Net①文章,转载请联系网站管理人员!
相关文章
-
1.C++怎么调用lib库啊?1LIB文件直接加入到工程文件列表中在VC中打开FileView一页,选中工程名,单击鼠标右键,然后选中"AddFilestoProject"菜单,在弹出的文件对话框中选中要加入DLL的LIB文件。然后在首先要使用该函数的...
-
1.怎么把电脑的c盘扩大使用Vista/windows7自带分区工具,可以做到硬盘无损重新分区分区。1、在桌面右键点击“计算机”-“管理”,打开的计算机管理窗口,在打开的计算机管理窗口的左侧,鼠标左键单击选“磁盘管理”打开磁盘管理...
-
1.最近C盘的剩余空间突然变小了,怎么办?可以这样释放一些C盘空间:1.打开“我的电脑”-“工具”-“文件夹选项”-“查看”-在“显示所有文件和文件夹”选项前打勾-再按“确定”2.删除以下文件夹中的内容:C:\DocumentsandSettings\...
-
1..NET中怎么调用COM组件.NET在设计之初就考虑到了如何方便的利用现有的各种技术资源,这也是微软的一贯作风,.NET的强大之处也可见一斑。.NET提供了大量的类库来方便的实现同COM的相互操作,其中很重要的一个名称空间...