您的位置:首页 > 其它

静态库与动态库

2014-01-25 23:55 204 查看
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#是完全面向对象的语言, 方法必需在类中.


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: