静态库与动态库

来源:互联网 发布:数控车床左牙怎么编程 编辑:程序博客网 时间:2024/05/19 19:30

Linux下静态库(.a)的例子:

MyLib.h:位于Include文件夹下:

#ifndef MYLIB_H_#define MYLIB_H_int Add(int a, int b);#endif

MyLib.cpp:位于Lib文件夹中

#include "MyLib.h"int Add(int a, int b){   return a + b;}
现在要编译生成libMyLib.a静态库:

1, 先生成MyLib.o,由于头文件和源文件不在同一目录下:

桌面/denvelop/Lib$ g++ -c -I /home/xq/桌面/denvelop/Include/ MyLib.cpp

2, 生成静态库:

桌面/denvelop/Lib$ g++ -c -I /home/xq/桌面/denvelop/Include/ MyLib.cpp

这里需要生成内容表:这一步不是必需的, 但做了也无妨

桌面/denvelop/Lib$ ranlib libMyLib.a


main.cpp:

#include "MyLib.h"#include <iostream>int main(){   int a = 10, b = 10;   int sum = Add(a, b);   std::cout<<sum<<std::endl;   return 0;}
3, 使用静态库:

桌面/denvelop$ g++ -I /home/xq/桌面/denvelop/Include/ -o main main.cpp /home/xq/桌面/denvelop/Lib/libMyLib.a
注意这里的包含和连接的顺序


linux下动态库(.so)的例子:

MyLib.h(同MyLib.cpp在同一目录中) MyLib.cpp main.cpp  同上面代码完全一样只是编译方式不同

这里使用-fpic 与 -shared 生成动态库

桌面/denvelop/Lib$g++ -fpic -shared MyLib.cpp -o libMyLib.so


现在就可以使用动态库:

但是动态库使用要将.so文件放到/usr/lib下

然后编译main.cpp

桌面/denvelop#g++ -I /home/xq/桌面/denvelop/Include/ -o main main.cpp -L /usr/lib/ -lMyLib


在Windows下,的静态库(.lib)下没什么太大的区别, 只是编译器上的设置问题:

win下静态库的例子:

代码于上面完全一样, 就不再给出源码, 直接说步骤:

1, 新建项目, 选择win32控制台项目,

2, 选择静态库, 可以去掉预编译头选项, 点击完成.

3, 写好代码,生成,就可以发现在Release(DEBUG)文件夹下有.lib的静态库文件了


使用静态库:

1, 打开项目属性

2, C/C++ => 常规 =>附加包含目录 ,这里添加静态库头文件所在目录.

3, 连接器 => 常规 => 附加库目录, 这里添加静态库文件所在目录

4, 连接器 => 输入 => 附加依赖项 , 这里添加静态库的名称, 注意要全名, 包括后辍名.lib



win下动态库的例子:

在win平如下动态库与静态库有很大的不同,

能被外部访问的函数名必需要加上:_declspec(dllexport) 关键字:

#ifndef MYLIB_H_#define  MYLIB_H__declspec(dllexport) int Add(int a, int b);#endif

这样在生成DLL的文件夹中, 你将看到有.dll的文件和一个.lib的文件, 在生成动态库的时候, *.lib文件并不是静态库, 而是引入库文件.


使用动态库:

1, 打开项目属性

2, C/C++ => 常规 =>附加包含目录 ,这里添加动态库头文件所在目录.

3, 连接器 => 常规 => 附加库目录, 这里添加引入库文件所在目录

4, 连接器 => 输入 => 附加依赖项 , 这里添加引入库文件的名称, 注意要全名, 包括后辍名.lib

5, 确保动态库文件与你的使用程序在同一目录中.


但是, 有时候, 如果动态库并没有提供相应的头文件,那么上述第3步就没必要了,

我们可以把动态库中的函数声明在使用动态库的程序中, 如下:

#include <iostream>_declspec(dllimport) int Add(int a, int b);int main(){int a = 10, b = 10;int sum = Add(a, b);std::cout<<sum<<std::endl;std::cin.get();return 0;}

虽然头文件可以没必要, 但是引入库文件和动态库文件是必需要的.恩...你懂的!

由于C++的改名问题,函数重载的原因, 所以C++函数编译完后, 并不是实际上的函数名, 简单的做法是使用extern "C"来声明函数,

这样就表示,这是一个基于C语言定义的函数

MyDLL.h:

#ifndef MYLIB_H_#define  MYLIB_H_extern"C" _declspec(dllexport) int Add(int a, int b);#endif


MyDLL.cpp

#include "MyDLL.h"extern"C" _declspec(dllexport) int Add(int a, int b){return a + b;}

main.cpp

#include <iostream>extern"C" _declspec(dllimport) int Add(int a, int b);int main(){int a = 10, b = 10;int sum = Add(a, b);std::cout<<sum<<std::endl;std::cin.get();return 0;}

这样就可以解决函数改变的问题

那么, 如果想让C++动态库的函数能被C#程序引用, 那么就必将该函数设定为_stdcall, 因为C/C++的默认调用约定为 _cdecl,

MyDLL.h

#ifndef MYLIB_H_#define  MYLIB_H_extern"C" _declspec(dllexport) int _stdcall Add(int a, int b);#endif


MyDLL.cpp

extern"C" _declspec(dllexport) int _stdcall Add(int a, int b){return a + b;}


C#main.cs:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Runtime.InteropServices;namespace ConsoleApplication1{    class Program    {        [DllImport("Libtest.dll")]        extern static int Add(int a, int b);        static void Main(string[] args)        {            int sum = Add(10, 50);            Console.WriteLine(sum.ToString());            Console.ReadKey();        }    }}

C# 在引用时C++动态库时, 只需要注意将动态库文件放在与执行程序相同的目录下就可以了,

然后是用C#的 DllImport特性来引用, 注意该方法必需以extern 和static 修饰. 因为C#是完全面向对象的语言, 方法必需在类中.





0 0
原创粉丝点击