我是靠谱客的博主 幽默流沙,最近开发中收集的这篇文章主要介绍MATLAB转C/C++常见问题总结楔子注意点其他总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

楔子

本指南试图帮助用户写出在转C过程中尽量少报错的Matlab m文件,其中更多是一些编程范式上的问题,在此记录下来,帮助后人写出无缝转C的代码。

Author: Y. F. Zhang

Time: 2022.4.16

注意点

使用变量前声明变量

这一点在matlab中时可以容忍的,但对于一般编程语言是无法容忍的。使用一个变量前请预分配变量内存(注意预分配内存不是简单前面给个 =0就可以了,得是相应维度的预分配):

tmp = zeros(6, 6); % 预分配内存
for i = 1 : 6
	tmp(:, i) = ones(6, 1);
end

m文件中内联嵌套scripts

不要这么干不要这么干不要这么干… 目前转c是不支持内联嵌套scripts的:

% main.m
a = 2;
b = zeros(3, 3);
init_para; % init_para.m 为scripts
% others
% others...

有多种方案解决,例如:

  1. init_para代码内联进来(也就是直接复制过来);
  2. init_para写成无参函数调用;

不允许离开变量作用域后使用变量

在matlab中对变量的作用域这个概念弱化了许多,下面这段代码在matlab下是能正常运行的:

for i = 1 : 100
	% do something
end
plot([i, i + 1], [10, 11]); 

变量 i 在离开了for循环作用域后继续使用,这在c是不允许的。

不允许动态分配内存语法

matlab下常用动态分配数组语句:

array = [];
for i = 1 : 100
	array = [array, i];
end

这种语法转c报错,如果想达到相同效果(预分配可能导致剩余部分0,但实际却不需要它们),可以使用如下方法:

array = zeros(1, 1000);
i = 0;
for i = 1 : 1000
	if done, break; end % done用于判断结束
	array(i) = i;
end
tmp_array = zeros(1, i);
tmp_array = array(1 : i);

不要用load

load转不了,或者说io类函数可能都转不 了。

别使用matlab的高级函数

例如: care fsolve等等,若要使用,只能从底层自己实现了。

解决这个真的是纯纯的运气活加体力活,能否解决取决于google有没有相同案例,大多数替代包都发布linux版本。就算能替代,首先需要将m文件中对应语句注释掉后转c然后还要去转出来的代码中定位该语句,之后还要把包移植过来解决接口输入输出,最后还要测试…

函数返回值要确保逻辑有值

function y = foo()
flag = 1;
if flag == 1
	y = 2;
end
end

像上面这种代码虽然y一定等于2输出,但逻辑上没有在else中对y赋值就是存在歧义的。解决方法在一开始对y赋值0。

深度学习转C

LSTM转mkldnn转不了,arm树莓派可以,要用网上的《xxxLSTM c实现》很难,除非你对LSTM的每个细节了如指掌…

一个m函数文件写一个函数

在matlab中一个m写多个函数是允许的,方便函数内部调用,但转c过程中会出错。解决方案:

  1. 内联地将内部函数复制到调用地方;
  2. 重新建立一个m文件(推荐);

注释掉一些没用的代码

包括但不限于:

  1. 画图相关代码;
  2. 与业务逻辑无关的打印代码;
  3. et.al

尽量少用global

matlab转c目前也是支持global的,只需要在转前添加函数中所有global变量,并定义其维度、类型以及初始值(若未定义,在使用之前必须初始化),注意以下情况是不允许的:

  • 在事先添加了global x和y的前提下,对y进行了初始化而未对x初始化,之后直接在函数中令x = y。这在matlab中是允许的,但转c是会出错的。

使用global会严重影响代码的可阅读性和封装性,一个实现某一功能的特定函数若使用了global变量,会影响它无缝移植到另外相同问题上,另外使用global变量之前很难定位上一个修改它的代码段,会增强程序之间的耦合性。

  • 若执意使用global,在转c的prj文件中请初始化所有global变量为任意值(zeros就行),并在使用它前赋予真正的值。否则会出现许多size mismatch报错。
  • 使用global的程序员大都想减少函数的大量传参,可以考虑使用参数句柄的方式传参,并输出修改后的参数句柄。function out_para_bar = func(in_para_bar)
% others
logged_signals = func(logged_signals);
% others

其他

编程习惯

  • 写完一份m后 ctrl A右键选择 智能缩进让所有代码快速缩进一下,否则看起来很凌乱。
  • 一些必要的空格,例如 tmp = [2, 3, 4]; for i = 1 : 100 使代码整体美观。
  • 不需要的函数输出用 ~代替。
  • 预分配内存。

tmwtypes.h

转完后的代码至少缺少tmwtypes.h这个头文件,在matlab->extern->include目录下将其拷贝到自己的工程中(或者直接配置vs include目录)。

转c++设置

若转c++,在设置中将标准设为c++11,但这不是必须的。

修改报错代码

每进行一次对m的大修(在转c过程中修改报错),回到m中重新运行一下代码看修改是否影响原本代码的运行结果。否则容易出现修改很多地方后原本代码都运行出错的情况。

总结

“尽量用底层语言的编程思维来写matlab”。

最后

以上就是幽默流沙为你收集整理的MATLAB转C/C++常见问题总结楔子注意点其他总结的全部内容,希望文章能够帮你解决MATLAB转C/C++常见问题总结楔子注意点其他总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部