文章目录
- 0 背景
- 1 Matlab有用代码提取
- 2 转换为C++
-
- 3 改写转换后的C++代码
- 3.1 指定输入的文件
- 3.2 改写处理`Data`和`Data1`结构的数据
- 4 福利
0 背景
本文是Matlab代码转C++的第二篇,目的是把一个更为复杂的Matlab项目代码转换为C++,以便打包成动态链接库,以供Java或C++调用。转换的难点,在于需要大量改写转换后的代码,把固定的输入数据,转成可以指定文件的方法,并把对数据结构做适当的处理以便调用放获取数据。
以下是文件的目录结构,untitled.m
调用了从上往下的前三个.m
文件,并且untitled.m
文件中的内容比较多,改写起来也不容易。
matlab运行后的结果(我们需要做的就是把matlab代码转成C++,然后使用其他语言调用C++代码,可以得到输出表格中的数据):
1 Matlab有用代码提取
以下为Matlab项目入口的untitled.m
的部分原代码:
function varargout = untitled(varargin)
% UNTITLED MATLAB code for untitled.fig
% UNTITLED, by itself, creates a new UNTITLED or raises the existing
% singleton*.
%
% H = UNTITLED returns the handle to a new UNTITLED or the handle to
% the existing singleton*.
%
% UNTITLED('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in UNTITLED.M with the given input arguments.
%
% UNTITLED('Property','Value',...) creates a new UNTITLED or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before untitled_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to untitled_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help untitled
% Last Modified by GUIDE v2.5 25-May-2022 11:48:46
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @untitled_OpeningFcn, ...
'gui_OutputFcn', @untitled_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before untitled is made visible.
function untitled_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to untitled (see VARARGIN)
set(handles.Dimension,'String','');
set(handles.Numbers,'String','');
set(handles.Clusters,'String','');
set(handles.Iteration,'String','');
% Choose default command line output for untitled
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes untitled wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Executes on button press in Load.
function Load_Callback(hObject, eventdata, handles)
% hObject handle to Load (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% 数据载入控制
global data;
global data1;
[f,p]=uigetfile('*.mat');
filepath=[p,f]; %filepath即为文件路径
load(filepath);
data = Data;
data1 = Data1;
set(handles.Dimension,'String',num2str(size(Data,2)));
set(handles.Numbers,'String',num2str(size(Data,1)));
% --- Executes on button press in Reset.
function Reset_Callback(hObject, eventdata, handles)
% hObject handle to Reset (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
set(handles.Dimension,'String','');
set(handles.Numbers,'String','');
set(handles.Clusters,'String','');
set(handles.Iteration,'String','');
% --- Executes on button press in Perform.
function Perform_Callback(hObject, eventdata, handles)
% hObject handle to Perform (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global data;
global data1;
Cope = get(handles.Iteration,'String');
if isempty(Cope)
pause(0.25);
h=msgbox('请先填写最大迭代次数(50-500)');
uiwait(h,5);
else
[~,~,Phi] = PROMETHEE(data);
% clf;
% axes();
bar(handles.Net,Phi)
box off
% set(gca,'XTick',[20 40 60 80 100 120 140 160])
set(get(gca,'YLabel'),'String','The Net Outranking Flow','FontSize',16,'FontWeight','demi','LineWidth',1.5,'FontName','Times New Roman');
T=str2num(get(handles.Iteration,'String'));
[Ss,Uu,V,objFcn,ddmin,times,iter] = myfcm(Phi', T);
% figure(2)
% clf;
bar(handles.ObjFunction,Ss)
box off
set(gca,'Xtick',[1 2 3 4 5 6 7 8 9],'XTicklabel',num2str([2 3 4 5 6 7 8 9 10]'))
ylabel('Objective Function','FontSize',16,'FontWeight','demi','LineWidth',1.5,'FontName','Times New Roman')
xlabel('Number of Clusters','FontSize',16,'FontWeight','demi','LineWidth',1.5,'FontName','Times New Roman')
[~,OptClus]=min(Ss);
set(handles.Clusters,'String',num2str(OptClus+1));
membership = Uu{2};
for i=1:size(data,1)
[~,Label(i)]=max(membership(:,i));
end
% res1 = cell(length(find(Label==3)),1);
% res2 = cell(length(find(Label==2)),1);
% res3 = cell(length(find(Label==1)),1);
% res4 = cell(length(find(Label==4)),1);
% res5 = cell(length(find(Label==5)),1);
% OFva1 = cell(length(find(Label==3)),1);
% OFva2 = cell(length(find(Label==2)),1);
% OFva3 = cell(length(find(Label==1)),1);
% OFva4 = cell(length(find(Label==4)),1);
% OFva5 = cell(length(find(Label==5)),1);
% OFva
Resnet = cell(1,3);
Resnet{1} = Phi(find(Label==1));
Resnet{2} = Phi(find(Label==2));
Resnet{3} = Phi(find(Label==3));
meanOF = [mean(Resnet{1}) mean(Resnet{2}) mean(Resnet{3})];
[~,iii] = sort(meanOF,'descend');
[~,c]=sort(Resnet{iii(1)},'descend');
indexc = find(Label==iii(1));
indexc = indexc(c);
[~,c]=sort(Resnet{iii(3)},'descend');
indexc3 = find(Label==iii(3));
indexc3 = indexc3(c);
[~,c]=sort(Resnet{iii(2)},'descend');
indexc2 = find(Label==iii(2));
indexc2 = indexc2(c);
% OFval1=Phi(indexc);
% OFval3=Phi(indexc3);
% OFval2=Phi(indexc2);
Result1 = cell(size(data,1),1);
Result1{1} = 'rank 1';
for i=2:length(indexc)+1
Result1{i}=data1{indexc(i-1)};
end
% Num = size(data,1);
% xlswrite('Res1.xls',res1,2,'A1');
% xlswrite('Res1.xls',OFval1,1,['A',num2str(length(res11)+1)]);
Result1{1+length(indexc)} = 'rank 2';
for i=2:length(indexc2)+1
Result1{i+length(indexc)}=data1{indexc2(i-1)};
% OFval2{i}=Phi(indexc2(i));
end
% xlswrite('Res1.xls',res2,1,'C1');
% xlswrite('Res1.xls',OFval2,2,['A',num2str(length(res22)+1)]);
Result1{1+length(indexc)+length(indexc2)} = 'rank 3';
for i=2:length(indexc3)+1
Result1{i+length(indexc)+length(indexc2)}=data1{indexc3(i-1)};
% OFval3{i}=Phi(indexc3(i));
end
% for i=1:length(res22)+length(res33)+length(res11)
% Result1{i}
% end
% xlswrite('Res1.xls',Result1);
% Res1=xlsread('Res1.xls');%读取文件datafile.xlsx,并存入data中
set(handles.ResultTable,'data',Result1);%将data中的文件以Data的形式设置在句柄为uitable1的表格中。
end
% xlswrite('Res1.xls',OFval3,3,['A',num2str(length(res33)+1)]);
% 净值
下面是转换后的代码(找到原代码中输出的部分,然后做适当修改后,改写成方法,该方法可以调用其他方法):
function [Result1, Clusters, Phi, Ss] = Perform(data,data1,T)
[~,~,Phi] = PROMETHEE(data);
[Ss,Uu,~,~,~,~] = myfcm(Phi', T);
[~,OptClus] = min(Ss);
Clusters = OptClus+1;
membership = Uu{2};
dataSize=size(data,1);
Label=coder.nullcopy(zeros(1,dataSize));
for i=1:dataSize
[~,Label(i)]=max(membership(:,i));
end
Resnet = cell(1,3);
Resnet{1} = Phi(Label==1);
Resnet{2} = Phi(Label==2);
Resnet{3} = Phi(Label==3);
meanOF = [mean(Resnet{1}) mean(Resnet{2}) mean(Resnet{3})];
[~,iii] = sort(meanOF,'descend');
[~,c]=sort(Resnet{iii(1)},'descend');
indexc = find(Label==iii(1));
indexc = indexc(c);
[~,c]=sort(Resnet{iii(3)},'descend');
indexc3 = find(Label==iii(3));
indexc3 = indexc3(c);
[~,c]=sort(Resnet{iii(2)},'descend');
indexc2 = find(Label==iii(2));
indexc2 = indexc2(c);
Result1 = cell(dataSize,1);
for i=1:dataSize
Result1{i}='000';
end
Result1{1} = 'rank 1';
for i=2:length(indexc)+1
Result1{i}=data1{indexc(i-1)};
end
Result1{1+length(indexc)} = 'rank 2';
for i=2:length(indexc2)+1
Result1{i+length(indexc)}=data1{indexc2(i-1)};
end
Result1{1+length(indexc)+length(indexc2)} = 'rank 3';
for i=2:length(indexc3)+1
Result1{i+length(indexc)+length(indexc2)}=data1{indexc3(i-1)};
end
end
2 转换为C++
参考之前的方法,做C++代码转换,需要注意的时,在设定变量类型时,需要做适当修改,不能使用原始的自动化生成的变量。
2.1 设定变量类型
如果使用了自动检测的,就会爆出如下的错误:
这是改写前的数据类型:
这是改写后的数据类型:
2.2 预先和定义声明变量
这是原始版本:
indexc = find(Label==iii(1));
indexc = indexc(c);
Result1{1} = 'rank 1';
for i=2:length(indexc)+1
Result1{i}=data1{indexc(i-1)};
end
这是改写后的版本:
Result1 = cell(dataSize,1);
dataSize=size(data,1);
for i=1:dataSize
Result1{i}='000';
end
Result1{1} = 'rank 1';
for i=2:length(indexc)+1
Result1{i}=data1{indexc(i-1)};
end
3 改写转换后的C++代码
转换出来的C++代码的示例代码并不能直接使用,我们需要对其进行修改。
下面是转换后的示例代码example/main.cpp
(只有固定的输入【定死了的.mat文件】、输出):
static void main_Perform()
{
coder::array<cell_wrap_0, 2U> data1;
coder::array<cell_wrap_0, 1U> Result1;
coder::array<double, 2U> Phi;
coder::array<double, 2U> data;
double Ss[9];
double Clusters;
// Initialize function 'Perform' input arguments.
// Initialize function input argument 'data'.
data = argInit_UnboundedxUnbounded_real_T();
// Initialize function input argument 'data1'.
data1 = argInit_1xUnbounded_cell_wrap_0();
// Call the entry-point 'Perform'.
Perform(data, data1, argInit_real_T(), Result1, &Clusters, Phi, Ss);
}
下面我们进行改写。
3.1 指定输入的文件
需要读取的ranking.mat
文件的结构如下:
Data1
中存储100个字符串大学名称:
Data
中则是一个100x5
的分数矩阵:
我们使用mat.h
中的方法,读取mat
文件并判断结构:
const char* matPath= "/Users/mac/Matlab/UniversityRankTest/codegen/lib/Perform/ranking.mat";
MATFile* pmatFile = matOpen(matPath, "r");
if (pmatFile == NULL)
{
printf("mat数据读取失败!");
return ;
}
matData = matGetVariable(pmatFile, "Data");
if (matData == NULL)
{
printf("结构体中Data数据不存在!");
return ;
}
matData1 = matGetVariable(pmatFile, "Data1");
if (matData1 == NULL)
{
printf("结构体中Data1数据不存在!");
return ;
}
matClose(pmatFile);
3.2 改写处理Data
和Data1
结构的数据
下面是改写处理Data
的数据(把写死的维度数据,改成变动的实际获取;被注释的部分为原始代码):
coder::array<double, 2U> argInit_UnboundedxUnbounded_real_T(mxArray* data)
{
coder::array<double, 2U> result;
int N = mxGetN(data);
int M = mxGetM(data);
result.set_size(M, N);
double* test = mxGetPr(data);
for (int idx0{0}; idx0 < M; idx0++) {
for (int idx1{0}; idx1 < N; idx1++) {
result[idx0 + M * idx1] = test[idx0 + M * idx1];
}
}
return result;
}
下面是改写处理Data1
的数据:
coder::array<cell_wrap_0, 2U> argInit_1xUnbounded_cell_wrap_0(mxArray* data)
{
coder::array<cell_wrap_0, 2U> result;
int N = mxGetN(data);
result.set_size(1, N);
for (int idx1{0}; idx1 < N; idx1++) {
mxArray * test = mxGetCell(data, idx1);
result[idx1] = argInit_cell_wrap_0(test);
}
return result;
}
cell_wrap_0 argInit_cell_wrap_0(mxArray* data)
{
cell_wrap_0 result;
std::string str = mxArrayToString(data);
int N = mxGetN(data);
result.f1 = argInit_1xUnbounded_char_T(str, N);
return result;
}
coder::array<char, 2U> argInit_1xUnbounded_char_T(std::string data, int N)
{
coder::array<char, 2U> result;
result.set_size(1, N);
for (int idx1{0}; idx1 < N; ++idx1) {
result[idx1] = data[idx1];
}
return result;
}
最后是获得double数组的数据:
for (int i = 0; i < 9; ++i) {
SsData[i] = Ss[i];
}
bestGroupNum = Clusters;
for (int idx0{0}; idx0 < 100; idx0++) {
PhiData[idx0] = Phi[idx0];
}
最后,我们来对比一个原始版本(Matlab自动生成的代码)和改写后的代码版本:
原始版本:
static void main_Perform()
{
coder::array<cell_wrap_0, 2U> data1;
coder::array<cell_wrap_0, 1U> Result1;
coder::array<double, 2U> Phi;
coder::array<double, 2U> data;
double Ss[9];
double Clusters;
data = argInit_UnboundedxUnbounded_real_T();
data1 = argInit_1xUnbounded_cell_wrap_0();
Perform(data, data1, argInit_real_T(), Result1, &Clusters, Phi, Ss);
}
改写后的代码版本:
void main_Perform(int iterationNum, const char* matPath, char** univRank, double PhiData[], double SsData[], double& bestGroupNum)
{
coder::array<cell_wrap_0, 2U> data1;
coder::array<cell_wrap_0, 1U> Result1;
coder::array<double, 2U> Phi;
coder::array<double, 2U> data;
double Ss[9];
double Clusters;
mxArray* matData = NULL;
mxArray * matData1 = NULL;
MATFile* pmatFile = matOpen(matPath, "r");
if (pmatFile == NULL)
{
printf("mat数据读取失败!");
return ;
}
matData = matGetVariable(pmatFile, "Data");
if (matData == NULL)
{
printf("结构体中Data数据不存在!");
return ;
}
matData1 = matGetVariable(pmatFile, "Data1");
if (matData1 == NULL)
{
printf("结构体中Data1数据不存在!");
return ;
}
matClose(pmatFile);
data = argInit_UnboundedxUnbounded_real_T(matData);
data1 = argInit_1xUnbounded_cell_wrap_0(matData1);
Perform(data, data1, iterationNum, Result1, &Clusters, Phi, Ss);
for(int i = 0;i < 101;i++){
univRank[i] = (char*)malloc(sizeof (char) * 256);
}
for (int i = 0; i < 101; ++i) {
std::string tmp = Result1[i].f1.operator std::string();
strcpy(univRank[i], tmp.c_str());
}
for (int i = 0; i < 9; ++i) {
SsData[i] = Ss[i];
}
bestGroupNum = Clusters;
for (int idx0{0}; idx0 < 100; idx0++) {
PhiData[idx0] = Phi[idx0];
}
}
4 福利
matlab原码、c++转换后代码的资源链接, 提取码: 5vjp
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)