Calling C functions using MATLAB.

I have a simple c function stored in clibs.c. The C file looks like the following:
/////clibs.c
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <mex.h>
#include "shrhelp.h"
#include "clibs.h"
EXPORTED_FUNCTION void twoBP(double *xdot, double *x){
xdot[0] = x[3];
xdot[1] = x[4];
xdot[2] = x[5];
xdot[3] = x[0];
xdot[4] = x[1];
xdot[5] = x[2];
return;
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray*prhs[] )
{
}
////end clibs.c
I also have the associated header file (clibs.h):
////clibs.h
#ifndef clibs_h
#define clibs_h
#include "shrhelp.h"
/* Function declarations */
EXPORTED_FUNCTION void twoBP(double *, double *);
#endif
///end clibs.h
In order to call twoBP function form MATLAB I simply used the follwing statemes:
mex clibs.c
loadlibrary('clibs')
xdot = zeros(1,6);
x = [1,2,3,4,5,6];
xdot = calllib('clibs','twoBP',xdot,x);
The enviroment is working and it returns xdot = [4,5,6,1,2,3] as expected.
Furthermore I can verify that the library had been well loaded by typing in the command window...
>>libfunctions('clibs')
which returns...
Functions in library clibs:
twoBP
My problem appears when I try to compile a slightly different C function:
EXPORTED_FUNCTION void twoBP(double *xdot, double *x,void (*camp)(double x, double *y, int n, double *f)){
xdot[0] = x[3];
xdot[1] = x[4];
xdot[2] = x[5];
xdot[3] = x[0];
xdot[4] = x[1];
xdot[5] = x[2];
return;
}
As you can see this new twoBP function takes an extra input argument: a function defined as void (*camp)(double x, double *y, int n, double *f).
I modify clibs.h accordingly:
#ifndef clibs_h
#define clibs_h
#include "shrhelp.h"
/* Function declarations */
EXPORTED_FUNCTION void twoBP(double *, double *,void (*)(double, double *, int, double *));
#endif
However, when I try to execute the matlab code...
mex clibs.c
loadlibrary('clibs')
libfunctions('clibs')
It returns:
No methods for class lib.clibs.
I do not know how to fix this problem. Any idea?
Thank you for your attention.
Estel.

Respuestas (2)

James Tursa
James Tursa el 29 de En. de 2020
Editada: James Tursa el 29 de En. de 2020
This:
void (*camp)(double x, double *y, int n, double *f)
is not a function as you claim. It is a pointer to a function that has the specified signature (takes four inputs and doesn't return anything). So this expression that you have in the prototype
void (double, double *, int, double *)
is incorrect. I am guessing this is what you fed to MATLAB. Had you fed it into a compiler I think you would have gotten an error. The proper expression is the first one. Simply use that in your h file. Or if you don't like the variable names (they are optional and don't hurt anything), then just
void (*)(double, double *, int, double *)
Your prototype in the h file would be (if I remove that extra double which doesn't appear in the actual function signature):
EXPORTED_FUNCTION void twoBP(double *, double *,void (*)(double, double *, int, double *));

1 comentario

Estel Ferrer Torres
Estel Ferrer Torres el 30 de En. de 2020
Thank you for your replay. You are right. I change the header for EXPORTED_FUNCTION void twoBP(double *, double *,void (*)(double, double *, int, double *)); but I am still having exactly the same problem...

Iniciar sesión para comentar.

Estel Ferrer Torres
Estel Ferrer Torres el 30 de En. de 2020
Editada: Estel Ferrer Torres el 30 de En. de 2020
I tried to simplify my problem:
I define the ponter function *camp with only one input double *.
EXPORTED_FUNCTION void twoBP(double *xdot, double *x,void (*camp)(double x)){
xdot[0] = x[3];
xdot[1] = x[4];
xdot[2] = x[5];
xdot[3] = x[0];
xdot[4] = x[1];
xdot[5] = x[2];
return;
}
So the header file looks like this:
EXPORTED_FUNCTION void twoBP(double *, double *,void (*)(double));
With this simplification MATLAB detects the function twoBP and returns:
Functions in library clibs:
twoBP
However, when I define the pointer function with two inputs, MATLAB does not detect twoBP in the library and returns:
No methods for class lib.clibs.
I dont understand.

4 comentarios

James Tursa
James Tursa el 30 de En. de 2020
Editada: James Tursa el 30 de En. de 2020
I don't use loadlibrary myself, so I am not familiar with what function signatures might cause it problems. That being said, I would wonder what you think MATLAB should do with that function pointer. MATLAB calllib certainly can't pass it anything proper for that argument, so what would you expect it to do? Can you clarify how you intend to call your twoBP function from MATLAB? And in particular what you intended for that function pointer argument? Even for your simple case where loadlibrary detects the twoBP function, there is no way it can pass anything valid for that function pointer argument. So what do you expect to happen when you call it?
Estel Ferrer Torres
Estel Ferrer Torres el 30 de En. de 2020
The fact is that more than one C method have to be called in order to obtain the results. I would not have problems if I would call one by one from matlab passing the outputs of function 1 as inputs of function 2, etc. However my supervisor want that only one interface exists between MATALB and C so that I only obtain the finlay result and no intermediate results. The C code have been given to me and the functions are already defined taking other functions as input.
The problem is that the functinos in C takes as arguments other C functions, so I know that in some way I should have a MALTAB variable type "function" or something like this. Im agree with you and probably it does not exist.
However, I know that what I'm trying to do has been done with Python insted of MATALB. I thought I could do the same with MATALB.
What is your recomendation? To continue searching? To use Python insted of MATALB? or ...?
Thank you very much!
James Tursa
James Tursa el 31 de En. de 2020
I don't know how to advise based on what I know so far. How can Python pass a C function pointer to a C library?
Estel Ferrer Torres
Estel Ferrer Torres el 31 de En. de 2020
Editada: Estel Ferrer Torres el 31 de En. de 2020
Don't know exactly because I don't have the hole code, but something like this:
def rk78 (t, y, n, h, hmin, hmax, tol, vfield):
# Convert parameter to ctype friendly
tc = c_double(t)
yc = (c_double * n)(*y)
nc = c_int(n)
hc = c_double(h)
hminc = c_double(hmin)
hmaxc = c_double(hmax)
tolc = c_double(tol)
# Call C-written RK78 integrator
clib.rk78nw(byref(tc), byref(yc), nc, byref(hc), hminc, hmaxc, tolc, vfield)
# Modify Python parameters
t = tc.value
h = hc.value
for i in range(n): y[i] = yc[i]
return t, h, y
where vfield is the pointer function. I think that you can initialize vfield like:
vfield = clib.functionName('input1', 'input2',...)
I think it does not return the outputs but a pointer to functionName.
But I'm not sure about this. I will ask to the person that write the code.

Iniciar sesión para comentar.

Categorías

Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Centro de ayuda y File Exchange.

Preguntada:

el 29 de En. de 2020

Editada:

el 31 de En. de 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by