其实这个资料网络上已经很多了,但是还是有一些细节让我捣鼓了很久,以及最近在做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下,如果非得这样做,请注意是否已经存在同名文件了,做好备份啊!
本文详细介绍了如何在Linux下创建动态链接库so文件,包括步骤和注意事项。同时,讨论了使用Matlab的mcc工具生成动态库时的问题,强调了ctf文件的重要性,并通过加法函数实验说明了调用过程。最后,提醒在处理动态库时避免同名库冲突导致的问题。
1846

被折叠的 条评论
为什么被折叠?



