Reputation: 79
I have a neural network trained in Matlab. Now, I want to use this network in Fortran. So, I followed the instructions given here: https://www.mathworks.com/help/deeplearning/ref/network.genfunction.html:
%% First, train a static network and calculate its outputs for the training data.
[x,t] = bodyfat_dataset;
bodyfatNet = feedforwardnet(10);
bodyfatNet = train(bodyfatNet,x,t);
y = bodyfatNet(x);
%% Next, generate and test a MATLAB function. Then the new function is compiled to a shared/dynamically linked library with mcc.
genFunction(bodyfatNet,'bodyfatFcn');
y2 = bodyfatFcn(x);
accuracy2 = max(abs(y-y2))
mcc -W lib:libBodyfat -T link:lib bodyfatFcn
This leads to the generation of files with extensions .c, .h and .so
In the Fortran code test.F90, I want to be able to compute y_test for a given x_test: y_test = bodyfatNet(x_test); Could you please tell me how this can be done/written?
Here below is my Makefile. I can make an executable from object file test.o and the shared object .so:
FORTRAN_COMPILER=gfortran
#FORTRAN_FLAGS=-O3 -Wall -Wextra -std=f2008
FORTRAN_FLAGS=-ffree-line-length-none
OBJ2 = libBodyfat.so
SRC1= test.F90
OBJ1 = $(SRC1:.F90=.o)
LIBS = $(OBJ1) $(OBJ2)
%.o: %.F90
@echo 'converting .F90 files to .o'
$(FORTRAN_COMPILER) $(FORTRAN_FLAGS) -o $@ -c $<
binary: $(LIBS)
@echo 'make an executable from objet files (.o) and the shared object (.so)'
$(FORTRAN_COMPILER) $(FORTRAN_FLAGS) -o $@ $(LIBS)
clean:
@echo 'cleaning'
@rm -f *.mod *.o binary
I am not certain if utilizing only ‘.so’ would suffice. But the more general question is how from test.F90 I can use the network.
UPDATE: As suggested by PierU, the problem is more of "how to call C routines from Fortran?". Below, you find the content of the generated .h file and .c file:
/*
* MATLAB Compiler: 8.2 (R2021a)
* Date: Wed Feb 8 15:21:13 2023
* Arguments: "-B""macro_default""-W""lib:libBodyfat""-T""link:lib""bodyfatFcn"
*/
#ifndef libBodyfat_h
#define libBodyfat_h 1
#if defined(__cplusplus) && !defined(mclmcrrt_h) && defined(__linux__)
# pragma implementation "mclmcrrt.h"
#endif
#include "mclmcrrt.h"
#ifdef __cplusplus
extern "C" { // sbcheck:ok:extern_c
#endif
/* This symbol is defined in shared libraries. Define it here
* (to nothing) in case this isn't a shared library.
*/
#ifndef LIB_libBodyfat_C_API
#define LIB_libBodyfat_C_API /* No special import/export declaration */
#endif
/* GENERAL LIBRARY FUNCTIONS -- START */
extern LIB_libBodyfat_C_API
bool MW_CALL_CONV libBodyfatInitializeWithHandlers(
mclOutputHandlerFcn error_handler,
mclOutputHandlerFcn print_handler);
extern LIB_libBodyfat_C_API
bool MW_CALL_CONV libBodyfatInitialize(void);
extern LIB_libBodyfat_C_API
void MW_CALL_CONV libBodyfatTerminate(void);
extern LIB_libBodyfat_C_API
void MW_CALL_CONV libBodyfatPrintStackTrace(void);
/* GENERAL LIBRARY FUNCTIONS -- END */
/* C INTERFACE -- MLX WRAPPERS FOR USER-DEFINED MATLAB FUNCTIONS -- START */
extern LIB_libBodyfat_C_API
bool MW_CALL_CONV mlxBodyfatFcn(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
/* C INTERFACE -- MLX WRAPPERS FOR USER-DEFINED MATLAB FUNCTIONS -- END */
/* C INTERFACE -- MLF WRAPPERS FOR USER-DEFINED MATLAB FUNCTIONS -- START */
extern LIB_libBodyfat_C_API bool MW_CALL_CONV mlfBodyfatFcn(int nargout, mxArray** Y, mxArray** Xf, mxArray** Af, mxArray* X, mxArray* _U4b, mxArray* _U4c);
#ifdef __cplusplus
}
#endif
/* C INTERFACE -- MLF WRAPPERS FOR USER-DEFINED MATLAB FUNCTIONS -- END */
#endif
This is the content of .c file:
/*
* MATLAB Compiler: 8.2 (R2021a)
* Date: Wed Feb 8 15:21:13 2023
* Arguments: "-B""macro_default""-W""lib:libBodyfat""-T""link:lib""bodyfatFcn"
*/
#define EXPORTING_libBodyfat 1
#include "libBodyfat.h"
static HMCRINSTANCE _mcr_inst = NULL; /* don't use nullptr; this may be either C or C++ */
#ifdef __cplusplus
extern "C" { // sbcheck:ok:extern_c
#endif
static int mclDefaultPrintHandler(const char *s)
{
return mclWrite(1 /* stdout */, s, sizeof(char)*strlen(s));
}
#ifdef __cplusplus
} /* End extern C block */
#endif
#ifdef __cplusplus
extern "C" { // sbcheck:ok:extern_c
#endif
static int mclDefaultErrorHandler(const char *s)
{
int written = 0;
size_t len = 0;
len = strlen(s);
written = mclWrite(2 /* stderr */, s, sizeof(char)*len);
if (len > 0 && s[ len-1 ] != '\n')
written += mclWrite(2 /* stderr */, "\n", sizeof(char));
return written;
}
#ifdef __cplusplus
} /* End extern C block */
#endif
/* This symbol is defined in shared libraries. Define it here
* (to nothing) in case this isn't a shared library.
*/
#ifndef LIB_libBodyfat_C_API
#define LIB_libBodyfat_C_API /* No special import/export declaration */
#endif
LIB_libBodyfat_C_API
bool MW_CALL_CONV libBodyfatInitializeWithHandlers(
mclOutputHandlerFcn error_handler,
mclOutputHandlerFcn print_handler)
{
int bResult = 0;
if (_mcr_inst)
return true;
if (!mclmcrInitialize())
return false;
{
mclCtfStream ctfStream =
mclGetEmbeddedCtfStream((void *)(libBodyfatInitializeWithHandlers));
if (ctfStream) {
bResult = mclInitializeComponentInstanceEmbedded(&_mcr_inst,
error_handler,
print_handler,
ctfStream);
mclDestroyStream(ctfStream);
} else {
bResult = 0;
}
}
if (!bResult)
return false;
return true;
}
LIB_libBodyfat_C_API
bool MW_CALL_CONV libBodyfatInitialize(void)
{
return libBodyfatInitializeWithHandlers(mclDefaultErrorHandler,
mclDefaultPrintHandler);
}
LIB_libBodyfat_C_API
void MW_CALL_CONV libBodyfatTerminate(void)
{
if (_mcr_inst)
mclTerminateInstance(&_mcr_inst);
}
LIB_libBodyfat_C_API
void MW_CALL_CONV libBodyfatPrintStackTrace(void)
{
char** stackTrace;
int stackDepth = mclGetStackTrace(&stackTrace);
int i;
for(i=0; i<stackDepth; i++)
{
mclWrite(2 /* stderr */, stackTrace[i], sizeof(char)*strlen(stackTrace[i]));
mclWrite(2 /* stderr */, "\n", sizeof(char)*strlen("\n"));
}
mclFreeStackTrace(&stackTrace, stackDepth);
}
LIB_libBodyfat_C_API
bool MW_CALL_CONV mlxBodyfatFcn(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
{
return mclFeval(_mcr_inst, "bodyfatFcn", nlhs, plhs, nrhs, prhs);
}
LIB_libBodyfat_C_API
bool MW_CALL_CONV mlfBodyfatFcn(int nargout, mxArray** Y, mxArray** Xf, mxArray** Af,
mxArray* X, mxArray* _U4b, mxArray* _U4c)
{
return mclMlfFeval(_mcr_inst, "bodyfatFcn", nargout, 3, 3, Y, Xf, Af, X, _U4b, _U4c);
}
Upvotes: 0
Views: 113