静态库与动态库

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#是完全面向对象的语言, 方法必需在类中.





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值