Los foros del Guille

Si no encuentras respuesta, puedes buscar en el sitio del Guille

Google
 

elGuille.hosting: Ofertas de alojamiento
posiblemente los mejores precios
¡¡¡ Ahora con el doble de casi todo !!!

Selecciona el foro y pulsa en mostrar:     Mostrar 
De tu interés (algunos de los avisos publicados)

12/mar/2008
Si quieres ver los mensajes que nadie ha contestado, puedes usar este link: http://foros.elguille.org/MensajesSinRespuestas.aspx
También lo tienes en la página de inicio.

  Foro: Pocket PC Cantidad:  Desde:   Hasta:    Aplicar   Responder 
Respuestas a: 52932 - Lamadas desde C# a DLL en Embedded C++ 4.0
IDAsuntoFechaNick 
52932 Lamadas desde C# a DLL en Embedded C++ 4.027/05/10 10:57acalanto   
Buenos días: soy nuevo en este foro y tras haber leido los tutoriales de C#->API, que me parecen muy buenos, decido postear esta pregunta por si algún usuario tiene una solución o me puede dar alguna pista. Puesto que me he registrado, colaboraré con vosotros para responder consultas en la medida de mis conocimientos y habilidades.

Estoy realizando una aplicación para un equipo que se controla mediante un dispositivo basado en Windows CE 4.2. En este equipo he instalado Compact FrameWork 2.0, pues esa versión de CE no admite el 3.0.

He creado una DLL con Visual Embedded C++ 4.0 y no la puedo construir con C++ .NET porque este código a su vez utiliza otra DLL del fabricante que produce problemas en C++.NET con punteros LPSTR que no puedo evitarlos.

La aplicación en C# declara las funciones de la DLL y las utiliza, normalmente todo funciona hasta que toco funciones que devuelven un tipo double....entonces se genera una Excepción no soportada que se propaga desde el propio punto de llamada, hasta la entrada en la aplicación (Main).

Pensando en que el FrameWork existente en el pocket pudiese tener problemas con VS 2008 . NET, he desarrollado un ejemplo (el que adjunto) muy simple para realizar las pruebas con la versión VS 2003 .NET.


Sigue lo mismo...Las funciones de la DLL las he declarado como WINAPI y como extern "C" double PASCAL EXPORT...y el problema persiste.

El código C++ bajo MFC es el que os muestro a continuación (sólo pongo las funciones del fichero *.cpp). El tipo WORD (byte en C#) lo devuelve correctamente.


****************************************************************************
EMBEDDED C++


Código:

extern "C"

WORD WINAPI getWrd(void) { return(2); }

extern "C" double PASCAL EXPORT getDbl(void) {
AFX_MANAGE_STATE(AfxGetStaticModuleState());
double valor=10.23;
return(valor);
}
****************************************************************

C# VS .NET 2003


Código:

//Carga de DLL
[DllImport("dll_Simple.dll", EntryPoint = "getWrd")]
public static extern byte getWrd();
[DllImport("dll_Simple.dll", EntryPoint = "getDbl")]
public static extern double getDbl();
///
/// Punto de entrada principal de la aplicación.
///

static void Main()
{
Application.Run(new frmPrincipal());
}
private void cmdWORD_Click(object sender, System.EventArgs e)
{
this.txtWORD.Text=String.Format("{0:F4}", getWrd());

}
private void cmdDOUBLE_Click(object sender, System.EventArgs e)
{
this.txtDOUBLE.Text=String.Format("{0:F4}", getDbl());
}
private void frmPrincipal_Load(object sender, System.EventArgs e)
{

}
}
*********************************************************************

Si alguien conoce la solución o una pista de por donde van los tiros...le vendo mi alma.

Gracias anticipadas.


PD: La misma librería, compilada con C++ 6.0 y ejecutada en PC, funciona a las mil maravillas.

Un cordial saludo.
IDAsuntoFechaNick 
52940 Re: Lamadas desde C# a DLL en Embedded C++ 4.0 (Resp: 52932)27/05/10 14:19RFOG   
Añade:

CallingConvention = CallingConvention.Cdecl

A la firma de los atributos de la importación.

Si las funciones en la DLL están definidas como C ese es el protocolo de llamada aunque tu pongas la palabra PASCAL en la firma de la función (que hace años que es una macro vacía en Win32).


Si esta respuesta resuelve tu duda, por favor pulsa en la de este mensaje. Gracias.
IDAsuntoFechaNick 
52943 Re: Lamadas desde C# a DLL en Embedded C++ 4.0 (Resp: 52932)27/05/10 15:21acalanto   
Muchísimas gracias por responder de forma tan inmediata.

Ya pensaba que podía ser alguno de los atributos de declaración pero el compilador de C# en un proyecto tipo Windows Mobile para la plataforma CE, solamente me permite declarar la gestón de memoria como tipo WinApi.

Como puedes ver en el cósigo C++ tengo las directivas WINAPI en una función y extern "C" PASCAL EXPORT en otra. Tambien he utilizado __stdcall pero no hay manera.

Creo que debe ser unproblema del Compact Framework 2.0, pero el dispositivo sobre el que tengo que desarrollar con WCE 4.2, no admite una versión superior.

Si se te ocurre alguna otra opción te estaré muy agredecido.


Un cordial saludo.


Si esta respuesta resuelve tu duda, por favor pulsa en la de este mensaje. Gracias.
IDAsuntoFechaNick 
52988 Re: Lamadas desde C# a DLL en Embedded C++ 4.0 (Resp: 52932)31/05/10 19:02acalanto   
Bueno, me respondo yo mismo porque al final he dado con la solución y creo que puede serle de gran utilidad a todo aquel que se encuentre en una situación parecida.

Si creamos una DLL con C++ y la invocamos desde una aplicación C#.NET (Supongo que desde VB.NET pasaría lo mismo) no existe ningún tipo de problema para pasar datos en ambas direcciones buscando, eso sí, la equivalencia de los diferentes tipos definidos en .NET y en C++ de versiones anteriores.

Una aplicación de prueba como la que lleve a cabo con C#.NET Windows Forms para PC y la librería DLL escrita en C++ 6.0, funciona perfectamente y todo lleva a una profunda confusión y a tomar caminos equivocados cuando lo migramos a una aplicación Windows Mobile CE desarrollando la DLL en Visual Embedded C++ 4.0

El secreto está en la plataforma Net Compact Framework, plataforma que no admite paso de parámetros de tipo numérico unsignedInt, unsignedLong, single, float y double, así como tampoco admite el paso natural de strings.

Todo este pequeño lio (muy poco y mal documentado) nos llevará a aplicar cierta lógica y aplicar declaraciones tipo en C++ tales como WINAPI, __stdtcall, __cdecl, con las que no conseguiremos otra cosa que volvernos locos y crear infinitas versiones de la DLL y de la aplicación.

SOLUCION:

A sabiendas que en C# funcionamos con código manejado y que vamos a operar con una librería que no pertenece a Framework (PInvoke) tendremos en primer lugar que hacer uso de la clase System.Runtime.InteropServices.

A renglón seguido declararemos las funciones exportadas en la librería:


Código:

[DllImport("GeoInland.dll", EntryPoint = "suma")]
public static extern void Orientar(ref double a, ref double b, ref double resultado);


Si nos fijamos, todos los parámetros INCLUIDO EL RESULTADO los pasamos por referencia y en C++ los recibimos como punteros a tipo double (AQUI ESTA EL TRUCO...TODO CON PUNTEROS).

Como si C++ nos devuelve un tipo double, Compact Framework no lo tratará adecuadamente, la solución es crear eb C++ funciones void, pasando la variable de reultado como un parámetro más de la función (RECORDAR: Las funciones C++ NO NOS PUEDEN DEVOLVER TIPOS DE DATOS MENCIONADOS) Esta técnica tiene el inconveniente de no poder asignar una función a un tipo double en C# de forma directa (como sería lo deseable).

En C# invocaremos la función suma de la siguiente forma


Código:

double resultado=0;
double a=10.23;
double b=14.89;
suma(a, b, resultado);
Como es engorroso tener que declarar todas las variables, podemos crear un wrapper en C# que resuelve este inconveniente:


Código:

public double wSuma(double a, double b) {
double resultado =0;
suma(a, b, resultado);
return(resultado);
}Con este envoltorio podremos resolver la suma desde cualquier lugar de la aplicación de la forma que parece más lógica, pues la excepción con tipos de datos incompatibles, la resuelve nuestro wrapper.



Código:

double resultado=wSuma(10.23,14.563);


Os puedo asegurar que algo tan sencillo a estado al punto de ponerme al borde del desequilibrio emocional, por ello, si alguién puede aprovechar este consejo le ahorrará muchos disgustos.

Espero que os resulte de utilidad.

Un cordial saludo.
[Editado: acalanto, 31/05/2010 19:03:58]


Si esta respuesta resuelve tu duda, por favor pulsa en la de este mensaje. Gracias.

 
(c) Guillermo 'guille' Som, 2005-2017  - foros.elGuille v1.0.5.3 (23/Mar/2009 14:50 GMT +1)  - (ASP.NET 2.0 v2.0.50727.8762)
 
Usuarios activos: 72 - App. iniciada: 23/11/2017 13:55:04 GMT - La hora GMT del servidor es: 23/11/2017 14:48:25 GMT