Llamar funciones escritas en C desde Matlab

MATLAB

MATLAB (Photo credit: Wikipedia)

Algunas veces, nos vemos en la necesidad de utilizar algunas funciones que no están presentes en las librerías de Matlab, para usos muy específicos o ya sea porque queremos un mayor rendimiento computacional en los cálculos o procedimientos que realizaremos o porque simplemente ya tenemos escritas en C dichas funciones y no vale la pena hacerlas de nuevo en .m.

Aunque no es posible hacer el llamado de una función escrita en C directamente desde la command window o de una función .m cualquiera, Matlab nos ofrece una herramienta para poder generar un “ejecutable” de este archivo .c para poder ser usado en el propio Matlab, el archivo que se genera, es llamado ‘mex’ que sería el equivalente en español a “ejecutable de Matlab” la extensión de este tipo de archivos varia dependiendo del sistema operativo usado, por ejemplo para Windows de 64 bits el archivo fuincion.c luego de compilarlo con mex queda nombrado como funcion.mexw64 y es este tipo de funciones las que posteriormente podemos llamar en la command window  o en cualquier fichero o función de Matlab.

La funciones que se espera usar en Matlab deben, sin embargo, cumplir con ciertos requisitos para que haya una buena comunicación entre los argumentos de entrada y salida, como explicaremos enseguida.

Antes que nada, hay que mencionar que en el caso de la funciones escritas en C, la función principal “main( )” se verá reemplazada por la función de la figura 1.

Imagen

fig1. prototipo de la función mexFunction y sus argumentos.

Como podemos observar la función que mencionamos anteriormente recibe 4 parámetros, que describiremos a continuación:

  • int nlhs:  este argumento nos indica el numero de argumentos de salida de la función, o en otras palabras, el número de variables presentes al lado izquierdo de la llamada desde Matlab.
  • mx Array *plhs[ ]: Matlab trabaja con un tipo de dato conocido como mxArray, similar a una estructura en el que ademas de contener el valor de la variable, contiene sus dimensiones como filas y columnas, si es formato double o si la variable es de tipo complejo, así, el argumento plhs[ ] es un arreglo de punteros, que precisamente ‘apunta’ a las variables presentes en el lado izquierdo (que esperan los valores que regresará la función).
  • int nrhs: es análogo a nlhs este entero, contiene la cantidad de argumentos que son entregados a la función cuando es llamada, en otras palabras, el número de variables o valores que se ponen entre paréntesis cuando se llama una función común de Matlab.
  • mxArray *prhs[ ]: este al igual que *plhs[ ] también es un arreglo de punteros, que en este caso apunta a las variables del lado derecho, que como mencionamos son las variables de tipo mxArray por defecto, que están entre paréntesis cuando se llama la función.

Para ilustrar lo que se acaba de decir, un ejemplo claro puede ser el siguiente:

asd

fig.2 función y sus argumentos

En este caso vamos a suponer que “función” es una función cualquiera que como resultado de la entrada de dos parámetros c ynos retorna los valores necesarios para almacenar en a yque son los argumentos de salida, para este ejemplo entonces podemos decir con seguridad que:

nlhs=2; porque son dos las variables o argumentos de salida que se encuentran al lado izquierdo de la sentencia (a y b).

plhs[0]= a la dirección de ‘a’ y por ende plhs[1] se encontraría apuntando a la variable ‘b’.

nrhs=2; debido a que son 2 los argumentos de entrada (o a la derecha del igual, las letras ‘hs’ el final del nombre de estas variables de refieren a hand side’ y la segunda letra de los nombres ‘l’ o ‘r’ se refieren a right o left).

prhs[0]=a la dirección de la variable ‘c’ y por supuesto prhs[1] se encontrará entonces apuntando a la variable ‘d’.

CONFIGURAR EL COMPILADOR PARA MEX.

Luego de haber comprendido lo respectivo a los argumentos de entrada-salida de nuestra función principal mexFunction(…), la cual sirve de interfaz entre Matlab y el y el propio código C, vamos a configurar el compilador respectivo para generar nuestros archivos  *.mex, para esto nos dirigimos entonces a la command window y escribimos ‘mex -setup’ como se ve en la figura 3, para que se despliegue el dialogo respectivo para el rastreo de compiladores disponibles en nuestro pc.

fig.3 setup de mex para buscar compilador.

fig.3 setup de mex para buscar compilador.

Al final  Matlab nos pregunta que si deseamos que ‘mex’ localice compiladores instalados, a lo cual respondemos que si (y) entonces veremos aparecer una lista de los compiladores que probablemente tengamos instalados en el computador, por lo regular con la versión de 64 bits de Matlab siempre suelen haber algunos problemas con este tema, puesto que esta versión no trae consigo un compilador propio, por lo tanto a algunos les será necesario descargar el SDK 7.1 (es un paquete para desarrolladores) de windows que ademas es libre y puede ser descargado desde su pagina oficial. Después de haber permitido que Matlab buscara compiladores disponibles nos aparecerá una “lista” para elegir el que deseemos, (el único compilador de 64 bits que tengo en mi pc es el de visual c++ contenido en el SDK 7.1), y se nos muestra de esta forma:

fig.4 selección del compilador

fig.4 selección del compilador

En mi caso digitaré el 1 para que Matlab tome este compilador para hacer los próximos *.mex y  *.exe ya que no hay más opciones. En las versiones de Matlab de 32 bits suelen haber varias opciones más, después de hacer nuestra selección Matlab nos volverá a preguntar si estamos seguros, a lo que responderemos afirmativamente (y).

fig. 5 Compilador finalmente configurado.

fig. 5 Compilador finalmente configurado.

De esta forma hemos terminado de configurar nuestro compilador para poder llevar a cabo proyectos posteriores que tengan que ver con ejecutables, o en general, compilaciones.

EJEMPLO COMPILACIÓN Y LLAMADO.

Existe una sola forma de compartir parámetros entre Matlab y nuestra función C y es, como ya vimos, mediante la famosa función “mexFunction(…)” pero al tratar con datos tipo mxArray pues también es muy diferente la forma de acceder a los contenidos de esos arreglos, para lo que Matlab nos entrega lo que lo podríamos llamar las funciones mx, son un grupo de funciones que nos permite hacer el paso entre el contenido de un mxArray a, por ejemplo, una cadena de longitud n, o por ejemplo extraer de un mxArray el valor entero de na variable. Pues bien, entre estas funciones podemos mencionar algunas comunes como: mxGetString(…), mxGetN(…), mxGetM(…), mxCalloc(…), etc; estas funciones tiene la convención de iniciar con las letras ‘mx’ precedidas de las sigueientes palabras, dependiendo de la tarea que cumplan, por ejemplo mxGetString(mxArray *) por simple inspección, viendo el nombre de la función se puede asegurar que lo que hace esta función es extraer una cadena de un puntero a mxArray y como esta muchas otras funciones son fácilmente identificables debido a que su nombre es muy claro. Este será tema de otro post yse verán ejemplos y explicaciones del los argumentos de cada una de ellas, ya que ahora nos dedicaremos a ilustrar lo comentado a hasta este punto sobre el llamado y la compilación de funciones C para Matlab.

Para este ejemplo se hará algo tan simple como una función que reciba 2 números a y b y los sume, así pues, inicialmente se escribe la función en cualquier compilador de C, iniciamos agregando los archivos de cabecera (indispensable, ya que ahí se encuentran las funciones mex y mx de Matlab) entonces para esto, como se ve en la figura 6, escribimos #include “mex.h” y también incluiremos matrix.h de la mimas forma (para ampliar la imagen puedes abrirla en otra pestaña del navegador).

fig. 6: función para sumar dos números ingresados desde Matlab.

fig. 6: función para sumar dos números ingresados desde Matlab.

En las sentencias condicionales , al usar las variables nlhs y  nrhs nos podemos asegurar si a la función se le estan ingresando más parámetros de los necesarios, o si por el contrario solo se esta ingresando uno al igual que verificar el número de variables de salida y de esta forma establecer el comportamiento para los casos donde se presente anomalía, en este caso solo necesitamos dos valores de entrada y solo se retorna uno que es el resultado de la suma.

Este archivo *.c lo guardaremos en cualquier carpeta del computador, en este caso el nombre será sumaC.c, posteriormente, nos dirigimos a Matlab y ubicamos el ‘Current Folder‘ en la carpeta en la que guardamos el archivo, en mi caso como se indica en la figura 7.

current_folder

fig. 7: Ubicar el Current Folder en el lugar donde se encuentra, el archivo .C

A continuación después de haber configurado los compiladores, solo queda escribir el comando mex seguido del nombre del archivo *.C, como se observa en la figura 8, es de suma importancia no olvidar poner la extensión del archivo, en este caso *.c .

fig. 8: Compilación del archivo .C

fig. 8: Compilación del archivo .C

En este caso, debido a la facilidad de la función pues no ocurrió ningún error, pero en caso de haber errores o inconsistencias en nuestra programación, en la command window, aparecerán los errores y la linea del código en que se cometieron.

Enseguida veremos que se genera en el directorio actual un nuevo archivo, que como dije antes, la extensión de este dependerá del sistema operativo y en ciertos casos dependiendo de la versión de Matlab se generará un .mex o una .dll que es una librería dinámica por sus siglas en ingles, en mi caso el archivo generado es el siguiente.

fig. 9: Archivo .mexw64 por Windows 64 bits.

fig. 9: Archivo .mexw64 por Windows 64 bits.

Después de esto, podemos entonces probar la función haciendo simplemente el llamado de la función ‘sumaC‘ como se llamaría cualquier otra función de Matlab, así podemos observar el siguiente resultado.

fig. 9: Ilustración llamado de la función desde Matlab.

fig. 10: Ilustración llamado de la función desde Matlab.

Es de esta sencilla forma que Matlab nos permite usar código (muchas veces mas eficiente) para se usado como función dentro de su entorno, el archivo sumaC.c se puede obtener aquí, y si hay alguna duda sobre el por qué de alguna sentencia, con gusto la contestaré, espero que este material les haya sido útil, igualmente algo de información nunca esta de más y mejor si es lo más completa posible, y de todas formas el conocimiento debe ser compartido. Un saludo y nos leemos en el próximo post.

2 comentarios en “Llamar funciones escritas en C desde Matlab

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s