matlab调用C的动态库
在使用matlab进行算法开发时,实现代码往往是C/C++的。而算法实现后,又需要通过matlab进行数据分析,对算法进行验证。
此时若使用matlab代码对数据进行分析,则会面临matlab实现与C代码实现不一致的情况。所以需要通过matlab调用c代码,实现历史数据回访验证。
使用matlab调用c代码的方法有几种,其中最方便的就是通过调用c动态库的方式。
网上的教程往往没有讲matlab的配置,调用前matlab需要配置编译器:
matlab需要配置mingw64编译器,可能需要版本对应。2016a对应gcc 6.2是没问题的。对应其他版本没有试过
1 | setenv ( 'MW_MINGW64_LOC' , 'C:\software\cmder\msys64\mingw64' ); |
然后输入: mex -setup 进行配置
然后可以根据提示,选择 mex -setup C++
C/C++部分代码需要编译为动态库,需要matlab调用的函数要通过extern "C"声明为C的命名规则。可传入结构体指针以及基础数据结构。函数可通过返回值和指针输出数据。
c/c++部分提供动态库dll或so,和h文件共2个文件。
通过matlab调用时,可通过头文件导入C部分的结构体。从而实现数据结构的传递。
测试C代码:(main.cpp)
1 #include "common.h"
2 #include "test.h"
3
4 int add(double a,float b,int c,u16 d,s8 e)
5 {
6 return a+b+c+d+e;
7 }
8 int struct_test(S_PRO_IN *pin) //测试结构体指针的输入
9 {
10 printf("val_u8 %d\n",pin->val_u8); //在matlab调用中无效
11 pin->val_u8++; //测试基础数据类型
12 pin->val_s8++; //测试基础数据类型
13 pin->val_u16++; //测试基础数据类型
14 pin->val_s16++; //测试基础数据类型
15 pin->val_u32++; //测试基础数据类型
16 pin->val_s32++; //测试基础数据类型
17 pin->val_u64++; //测试基础数据类型
18 pin->val_s64++; //测试基础数据类型
19 pin->val_float=9.2;
20 pin->val_double=-9.2;
21 pin->val_u32p[2]=10; //测试整数指针
22 return 2;
23 }
24 #ifndef SOMAKE //若是编译成exe
25 int main(int argc, char *argv[])
26 {
27 int i;
28 printf("add: %d\n",add(1,2,3,4,-1));
29 PDBG;
30 scanf("%c",(char)i);
31 }
32 #endif
头文件(test.h)
1 #ifndef TEST_H
2 #define TEST_H
3
4 #include "main.h"
5
6 //matlab调用dll时:
7 // 可定义结构体,一次传输
8 // 通过头文件进行接口交互
9 //
10
11 typedef struct S_PRO_IN_ //matlab中的内存布局是否一致?
12 {
13 u8 val_u8; //测试基础数据类型
14 s8 val_s8; //测试基础数据类型
15 u16 val_u16; //测试基础数据类型
16 s16 val_s16; //测试基础数据类型
17 u32 val_u32; //测试基础数据类型
18 s32 val_s32; //测试基础数据类型
19 u64 val_u64; //测试基础数据类型
20 s64 val_s64; //测试基础数据类型
21 float val_float;
22 double val_double;
23 u32 *val_u32p; //测试整数指针
24 } S_PRO_IN; //
25
26 #ifdef __cplusplus
27 extern "C"
28 {
29 #endif
30
31 int add(double a,float b,int c,u16 d,s8 e);
32 int struct_test(S_PRO_IN *pin); //测试结构体指针的输入
33
34 #ifdef __cplusplus
35 }
36 #endif
37
38 #endif
文件中,定义了2个接口函数,add和struct_test用于测试调用的传参和返回情况。
在24行定义了条件编译测试函数,用于使用exe对动态库的函数进行测试,并找到此编译器的依赖dll
代码编译成test.exe后,在Windows资源管理器中双击运行,会报错:
根据提示,在mingw64路径下将所缺失的dll复制到exe同目录下即可。
然后编译为动态库.so。编译选项加入: -D SOMAKE -fPIC,链接选项加入: -shared,编译为test.so
测试matlab代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | if not ( libisloaded ( 'test.so' )) [m1,m2] = loadlibrary ( 'test.so' , 'test.h' ); disp (m1); disp (m2); %显示变量内容 end libfunctions ( 'test' , '-full' ); %查看加载的函数列表 %构造指针 val_u32p=[1,2,3,4.8,-5]; %构造结构 pro_in.val_u8=3; pro_in.val_float=-2.1; pro_in.val_u32p= libpointer ( 'uint32Ptr' ,val_u32p); %pro_in_struct=libstruct('S_PRO_IN_',pro_in); %调用函数 a= calllib ( 'test' , 'add' ,1,2,3,4,-1); [b,c]= calllib ( 'test' , 'struct_test' ,pro_in); %函数返回值为b,c为指针对象 %注意,指针输入以后,输入对象是不变的,返回的c是输入指针变化后的对象 |
使用loadlibrary加载动态库,使用unloadlibrary卸载动态库。卸载了动态库,才能更新动态库。卸载前必须将所有用到的对象都清除掉。
1 | unloadlibrary ( 'test' ); %注意这里不要写扩展名,加载的时候不是dll,需要写扩展名 |
通过实验,得出数据传递过程中的几个结论:
- 构造数组时,可通过matlab中的double型数组,构造其他类型的数组,类型会自动转换,正负号、小数部分都会自动转换(小数部分是舍入)。
- 构造结构时,可不对所有域赋值
- 函数的参数如果是指针,指针所指的空间不会改变,函数内部对指针数据的改变会被复制一遍,放在返回列表中
- 调用函数时,返回值是一个数组,C函数的返回值放在第一位,函数中传入的参数如果是指针,会被复制一份,依次放在序列中。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧