Linux下动态链接库的创建和使用及C调用matlab动态库问题

本文详细介绍了如何在Linux下创建动态链接库so文件,包括步骤和注意事项。同时,讨论了使用Matlab的mcc工具生成动态库时的问题,强调了ctf文件的重要性,并通过加法函数实验说明了调用过程。最后,提醒在处理动态库时避免同名库冲突导致的问题。

其实这个资料网络上已经很多了,但是还是有一些细节让我捣鼓了很久,以及最近在做matlab mcc做成so文件供给c++调用的时候的一些问题。

一、首先如何制作Linux下的so 文件

【1】http://bbs.chinaunix.net/thread-1281954-1-1.html

【2】http://www.cnblogs.com/ardar/articles/357321.html

这两篇想必已经很清楚了。

首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:

  1.可以实现进程之间的资源共享。

   什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段.

  2.将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。

  3.甚至可以真正坐到链接载入完全由程序员在程序代码中控制。

程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们


步骤:

首先建立一个函数文件fun.cpp 以及头文件 fun.h

#include <iostream>

void fun1();
void fun2();


#include "fun.h"
using namespace std;

void fun1(){
cout<<"fun1() is called\n";
}
void fun2(){
cout<<"fun2() is called\n";
}



然后建立我们的Main.cpp

#include "fun.h"

int main()
{
fun1();
fun2();
}


接着开始编译 我们的函数库

gcc fun.cpp -fPIC -shared -o libfun.so
注意这里的命名方式libXXX.so  


接着就会看见我们的动态库了


然后编译我们的应用函数

g++ Main.cpp -L. -lfun -o MainApp
这里要注意,有的人用gcc会出现undefined cout的错误,因为我们用的是C++语言,所以还是要用g++编译

-L是指定动态链接库的目录  -l是制定库名字


接下来我们运行

./MainApp

会报错,无法加载的shared object

这是因为我们还没有告诉程序动态链接库的位置

三种方法告诉

(1)

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/你的库目录
(2)

更改/etc/ld.so.conf,添加我们的库目录,然后执行ldconf 

需要root权限

(3)加入/user/lib 或者/usr/lib64看你的机器位数,貌似拷贝的方法最凑效了,其他方法有时候行不通


二、matlab利用mcc制作动态库问题

在matlab制作so文件的时候也是要更改上述库目录的,还有生成的ctf必须和库放在一起,或者在库目录下!!!可以在ld.so.conf里面写入ctf文件位置

mcc -C选项可以生成ctf文件!!!

下面我就以广为流传的加法做实验吧。。更具有普遍性点

我的平台是ubuntu10.10+matlabR2009b

首先在matlab下,输入文件:

function z = myAdd(x, y)
 z = x + y;
end
然后在控制台上输入:

mcc -W cpplib:libmyAdd -T link:lib myAdd -C
必须加上-C选项,才能生成ctf文件(有的人貌似不用ctf也可以运行,但是我测试了,有的大点的程序就需要引入ctf对数据的定义,所以建议大家生成这个文件)

在当前目录下,我们主要利用到三个文件:libmyAdd.h  libmyAdd.so libmyAdd.ctf


这里我使用的是eclipse上的CDT完成的!

首先建立一个项目,选择gcc编译器。

选择该项目的属性,如下图所示,选择build选项,


(1)头文件目录gcc c++ compiler--->includes选项卡

加入:$MATLAB_ROOT/extern/include

$MATLAB_ROOT 这个变量指的是你的matlab根目录,这个变量系统压根就没有,需要你自己重写出来:比如说我的目录是:/home/ylf/App/matlab/extern/include


(2)库目录 GCC C++ Linker ---> Libraries

Libraries(-l)加入库名字:mwmclmcrrt   、  myAdd  (说明下:有的人加入的是mclmcrrt或者别的,大家可以看看别人都加了那些,反正我加了这两个就够了)

Library search path(-L)加入库目录:就是上面两个库的目录

$MATLAB_ROOT/runtime/glnxa64

以及libmyAdd.so的目录  这两个

注意:我在这种加入以后,编译是没有问题,但是在运行的时候无法找到动态库,不知到为什么,于是就 吧libmyAdd.so复制到/usr/lib64/目录下,。。。就可以解决,要是还是不行,再把libmyAdd.so目录加入到ld.so.conf里面,执行ldconfig 更新,我就不信还不行。

 

接下来文件里使用方法:

#include "mclmcrrt.h"
#include "mclmcr.h"
#include "mclcppclass"
#include "matrix"

#include "libmyAdd.h"

int main(){
  //初始化函数库
  if(!mclInitializeApplication(NULL,0)){
    cout<<"initial error"<<endl;
return 1;
}
//初始化我们的库
libmyAddInitialize();

//接下来可以使用了



  // 最后还要关闭
   libmyAddTerminate();
   mclTerminateApplication();
}


建议libmyAdd.h拷贝到源文件夹下,libmyAdd.so libmyAdd.ctf拷贝在工程下


使用mwArray作为交换的数据类型

mwArray使用方法如下:

//定义了3行4列的double类型的数据矩阵
mwArray a(3,4,mxDOUBLE_CLASS);
a(1,1) = 9;
a(3,4) = 10;//注意是从1开始计数的

//如果你的matlab使用了varargin这个变量的话,要是用cell数据类型来动态改变参数个数
mwArray input(1,2,mxCELL_CLASS);
mwArray arg1("color");
mwArray arg2("red");
input.Get(1,1).Set(arg1);
input.Get(1,2).Set(arg2);
//如果你需要更多的参数那就重复上述即可

//调用我们的库函数
mwArray x(1,1,mxDOUBLE_CLASS);

mwArray y(1,1,mxDOUBLE_CLASS);

mwArray z(1,1,mxDOUBLE_CLASS);

//具体函数怎么申明的,打开libmyAdd.h最下面可以看的
myAdd(1,z,x,y); 



由于我现在用的电脑上没有源文件。。。可能会有些表述不太正确,如果有啥问题可以留言,我会尽快回复~

由于版本问题,以及是否安装了mcr这个东东,貌似很难解决,我只在R200b上成功跑起来R2012没有成功。。。


补充下:

今天用chrome的时候突然启动不了了

报错是:look up error 

undefined symbol: FT_Get_Advance
使用命令

ldd /opt/google/chrome/chrome | grep freetype

你会发现,oops,我们的chrome居然使用了matlab里的libfreetype.so,天啊,居然同名。。

于是我把/etc/ld.so.conf里面的matlab路径删了,chrome可以重新启动了。。

这种同名库确实很淡疼,所以千万别乱复制到/usr/lib下,如果非得这样做,请注意是否已经存在同名文件了,做好备份啊!





评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值