Llamar a una funcion externa mandando una estructura

Soy principiante en arduino. Si pongo todo el codigo en el modulo .ino funciona bien. En cuanto lo dividido el 2 modulos aparece el error: undefined reference to `mp(prg)'. Creo que el problema esta en la definicion de la funcion pero no veo el problema. Gracias

En el modulo ES1.h tengo la estructura

struct prg {     
  int n= 2;     
  char *c= "ABC";  
} Prog;

En el modulo ES2.h tengo definida la funcion
void mp(prg p);

En el modulo ES2.cpp tengo la funcion

#include "Arduino.h"  
#include "ES1.h" 

void mp(prg &p) {  
  Serial.println(p.n);  
  Serial.println(p.c);  
}

En el modulo principal ES.ino tengo

#include "ES1h"  
#include "ES2.h"  
void loop() {  
  mp(Prog);  
}

La función mp definida en ES2.h y declarada en ES2.cpp no tienen el mismo tipo de parámetro, para el compilador son distintas. Imagino que te falta el & en el prototipo de la función, en ES2.h.
Saludos.

Te adelanto que lo probé, no funcionó y no encontré solución pero si hay un par de detalles que corregir (aunque no funcione :wink: ).
Aparte de lo que te marcó @harkonnen , en ES.ino falta setup() y falta inicializar el puerto Serial que usa ES2.cpp
Por otro lado hay un error de inclusión

#include "ES1h"

debería ser

#include "ES1.h"

No es necesario que crees dos archivos ya que te tendrás que "incluir" cada archivo en el siguente para no tener problemas de que se quede algo sin referenciar.

Generalmente en un archivo .h se hacen las declaraciones de los objetos, datos o estructuras que vas a utilizar y se pone la definición de las funciones que van a a manipular dichos objetos/estructuras.

Así la cebera es2.h puede quedar de la forma:

#ifndef _es1_h_
#define _es1_h_

struct prg {     
  int n= 2;     
  char *c= "ABC";  
} ;

void mp(prg &p);

#endif
  • La macro ifndef solo dejará que se incluya solo una vez.
  • No hace falta declarar un tipo para la estructura.
  • Declaras la función mp, que debe coincidir luego en el .cpp con el nombre y parametros.

El archivo es2.h quedará así:

#include "Arduino.h"  
#include "ES2.h" 

void mp(prg &p) {  
  Serial.println(p.n);  
  Serial.println(p.c);  
}

Se incluye la cacebera y se realiza la implementación de la funcion mp().

Por último en tu sketch debes crear una variable de dicha estructura para poder usarla e incluir solo el fichero de cabecera.


#include "ES2.h"  

prg Prog;

void setup() {
  
}
void loop() {  
  mp(Prog);  
}

Esta técnica es la que se usa generalmente para crear librerias y ficheros a parte. Si lo que quieres es usar tres ficheros ten en cuenta que tu archivo es1 lo debes incluir en todos los archivos de es2.

No se como agradecerte tu ayuda. Llevava mas de 1 mes colgado sin saber que hacer. Lo havia probado todo.

Soy un poco nuevo en todo esto del Arduino aunque me estoy atreviendo a hacer un projecto de Energia Solar un poco complejo. Ya tengo 72 y cuando tenia 30 habia programado mucho en Turbo C de Borland en programas importantes de control de hardware. Todavia no existia el Windows.

He probado tu programa y funciona correctamente. Pero no se cual es el error que he cometido en el mio.

En el programa que estoy haciendo disgongo de muchos modulos, però es la primera vez de definia una estructura en C++.

¿Es possible poner la funcion mp() en 1 modulo y la estructura en otro?. Porque estructuras como estas habra muchas que voy a tener que llamar desde distintos modulos.

En cualquier caso muchas gracias por tuantencion. Estaba desesperado

Salomo Beneit

Enviat: dimarts, 4 de juliol de 2023 7:55
Per a: sbeneit@gmail.com
Tema: [Arduino Forum] [Español/Software] Llamar a una funcion externa mandando una estructura



Imatge suprimida pel remitent.

|

victorjam
July 4

|

  • | - |

No es necesario que crees dos archivos ya que te tendrás que "incluir" cada archivo en el siguente para no tener problemas de que se quede algo sin referenciar.

Generalmente en un archivo .h se hacen las declaraciones de los objetos, datos o estructuras que vas a utilizar y se pone la definición de las funciones que van a a manipular dichos objetos/estructuras.

Así la cebera es2.h puede quedar de la forma:

#ifndef _es1_h_
#define _es1_h_

struct prg {     
  int n= 2;     
  char *c= "ABC";  
} ;

void mp(prg &p);

#endif

· La macro ifndef solo dejará que se incluya solo una vez.

· No hace falta declarar un tipo para la estructura.

· Declaras la función mp, que debe coincidir luego en el .cpp con el nombre y parametros.

El archivo es2.h quedará así:

#include "Arduino.h"  
#include "ES2.h" 

void mp(prg &p) {  
  Serial.println(p.n);  
  Serial.println(p.c);  
}

Se incluye la cacebera y se realiza la implementación de la funcion mp().

Por último en tu sketch debes crear una variable de dicha estructura para poder usarla e incluir solo el fichero de cabecera.


#include "ES2.h"  

prg Prog;

void setup() {
  
}
void loop() {  
  mp(Prog);  
}

Esta técnica es la que se usa generalmente para crear librerias y ficheros a parte. Si lo que quieres es usar tres ficheros ten en cuenta que tu archivo es1 lo debes incluir en todos los archivos de es2.

Muchas gracias por tu atencion. Seguire probando a ver si encuentro una solucion. El problema creo que lo tengo en la definicion de la estructura. Hace 1 mes que estoy con este problema y no se como solucionarlo

Muchas gracias

Salomo Beneit

Enviat: dilluns, 3 de juliol de 2023 22:15
Per a: sbeneit@gmail.com
Tema: [Arduino Forum] [Español/Software] Llamar a una funcion externa mandando una estructura



Imatge suprimida pel remitent.

|

harkonnen
July 3

|

  • | - |

La función mp definida en ES2.h y declarada en ES2.cpp no tienen el mismo tipo de parámetro, para el compilador son distintas. Imagino que te falta el & en el prototipo de la función, en ES2.h.
Saludos.

Si puedes crear un fichero diferente para las estructuras.

Por ejemplo puedes crear el fichero es1.h:

#ifndef _es1_h_
#define _es1_h_

struct prg {     
  int n= 2;     
  char *c= "ABC";  
} ;

#endif

En el has creado la estructura directamente. Obviamente debes incluir este fichero donde vayas a usar la estructura. En tu caso es el fichero es2.

Lo primero es crear la cabecera es2.h:

#ifndef _es2_h_
#define _es2_h_

#include "es1.h"

void mp(prg &p);

#endif

Si te das cuenta he tenido que incluir el fichero es1.h para que el compilador reconozca la estructura prg.

El fichero es2.cpp se queda exactamente igual:

#include "Arduino.h"  
#include "ES2.h" 

void mp(prg &p) {  
  Serial.println(p.n);  
  Serial.println(p.c);  
}

Dado que en es2.h ya se incluye es1.h el compilador ya sabe lo que es la estructura y no dará problemas.

Al sketch principal le ocurre lo mismo ya está incluido todo en es2.h por lo tanto se queda exactamente igual.

#include "ES2.h"  

prg Prog;

void setup() {
  
}
void loop() {  
  mp(Prog);  
}

De todas formas, es conveniente que cuando crees una estructura/objeto su definición y la definición de las funciones que lo manejan esten en el fichero .h y su implementación en el .cpp. Si tienes varias estructuras tienes que agruparlas teniendo en cuenta su contexto.

**Gracias de nuevo por tu atencion. He probado lo que me has dicho y funciona correctamente. **
*El problema que tengo es un poco mas complejo debido a que tengo estructuras todas ellas con las mismas variables, pero que pueden variar el nº de elementos de los char[] y las tengo situadas en el modulo st1.h

struct st1{ int n=2; char * s[2]= {"ab", "bc"};
  .
  .
struct stn{ int n=3; char * s[3]= {"a", "xx", "ddd"};

En el modulo principal .ino necesito llamar a una funcion mandandole cualquiera de estas estructuras

st2 st;
  mp(st);
  st3 st;
  mp(st);

Y en el modulo st1.cpp tendre la funcion mp(.............). Como puedo declarar esta funcion para que me haga referencia a una u otra estructura. ¿O hay algun otro metodo para hacerlo?

Creo que en realidad solo necesitas una estructura:

struct objeto {
  int numero;
  char *cadenas[];
};

numero será la variable donde se almacena el total de cadenas que existen en el objeto.

cadenas seran las cadenas de dicho objeto, tantas como el número indique.

Ahora debes crear variables de esa estructura "objeto".

objeto var1 = { 2, {"ab", "bc"} };
objeto var2 = { 3, {"a", "bc", "abc"} };
objeto var3 = { 4, {"d", "de", "def", "defg"} };

Obviamente el primer número indica el número de cadenas y el resto son las cadenas propiamente dichas. Precaución al colocar las llaves puesto que dará error.

Por último, crea la función para imprimir los datos. Como sabemos el numero de
cadenas podemos hacer un recorrido por cada una de ellas para mostrarlas:

void print(objeto &o) {
  Serial.println(o.numero);
  for (char i=0; i<o.numero; i++) {
    Serial.println(o.cadenas[i]);
  }
}

Aunque personalmente optaria por crear una clase y añadir métodos y funciones para añadir datos y modificar datos.

Si aplicas esto no será necesario tener multiples archivos de cabecera y cpp.

Ejemplo:

struct objeto {
  int numero;
  char *cadenas[];
};

// Inicialización de los objetos.
objeto var1 = { 2, {"ab", "bc"} };
objeto var2 = { 3, {"a", "bc", "abc"} };
objeto var3 = { 4, {"d", "de", "def", "defg"} };

void print(objeto &o) {
  Serial.println(o.numero);
  for (char i=0; i<o.numero; i++) {
    Serial.println(o.cadenas[i]);
  }
}
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  print(var1);
  Serial.print("---");
  print(var2);
  Serial.print("---");
  print(var3);
  Serial.print("---");
  delay(20000);
}
1 Like

Muchas gracias por tu atencion y amabilidad
:hugs: :hugs:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.