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