Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Port A C#...

Iniciado por TheAzazel, 17 de Octubre de 2005, 11:54:45 AM

« anterior - próximo »

Gezequiel

 Ok, gracias BeRSeRKeR!!
Por lo que veo no es muy dificil de C++ nativo a Managed, aunque despues a C# se vuelve un poco mas complejo...

[Offtopic]
Me eh dado cuenta que SharpDevelop, a pesar de poder crear projectos C++ no los puede compilar...
[/Offtopic]

Haber si ahora si entendo, abria que crear una clase llamada en este caso ILogSystem y en esa poner todas las funciones que en esta se incluyen, en el caso del ejemplo de BeRSeRKeR seria Msg y los parametros o lo que sea que va entre parentesis seria exactamente lo mismo pero en su version de .Net como es el caso de "char" a "string". Lo que no entendí fue porque en C++.Net tambien ahy que agregar "Object* arg __gc[]"

Eso seria en todos los casos??
O solo en este y en donde se requiera??
Porque segun tengo entendido eso de __gc es para avisar al compilador o ah quien sabe que es codigo unmanaged, estoy en lo cierto??
Pero porque todo el resto??

Gezequiel

 Ok, gracias BeRSeRKeR!!
Por lo que veo no es muy dificil de C++ nativo a Managed, aunque despues a C# se vuelve un poco mas complejo...

[Offtopic]
Me eh dado cuenta que SharpDevelop, a pesar de poder crear projectos C++ no los puede compilar...
[/Offtopic]

Haber si ahora si entendo, abria que crear una clase llamada en este caso ILogSystem y en esa poner todas las funciones que en esta se incluyen, en el caso del ejemplo de BeRSeRKeR seria Msg y los parametros o lo que sea que va entre parentesis seria exactamente lo mismo pero en su version de .Net como es el caso de "char" a "string". Lo que no entendí fue porque en C++.Net tambien ahy que agregar "Object* arg __gc[]"

Eso seria en todos los casos??
O solo en este y en donde se requiera??
Porque segun tengo entendido eso de __gc es para avisar al compilador o ah quien sabe que es codigo unmanaged, estoy en lo cierto??
Pero porque todo el resto??

Edit:
Estoy probando unas cosas en C#
Cuando en C++ nativo se pasa como parametro "void" cual seria la equivalencia de este en C#???
Porque si utilizo "void" me da "parametro no valido"

Seria para algo como esto:  public static extern byte GetState (void);

Esta mal usado??
Se usa otra cosa??

(!Edite el mensaje anterior y lo agrego como uno nuevo¡)

BeRSeRKeR

 Ese void no es necesario ponerlo ni en C++ y mucho menos en C#.

En cuanto al __gc, indica que ese recurso es managed, __nogc indica que es unmanaged.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

zupervaca

 ¿el c++ managed usa otro motor de ejecucion o es el mismo que el c#? es que si son diferentes la multiplataforma se iria al garate

BeRSeRKeR

 Todo lenguaje que sea administrado genera un lenguaje intermedio común (MSIL). Esa es la razón por la que se puede utilizar una dll desarrollada en Managed C++ dentro C# sin tener que hacer nada más que añadirla como referencia.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Gezequiel

 Necesito la ayuda de algun programador C# para probar un "intento" de portar la libreria a C# directamente sin pasar por C++.

Estaria buscando este programador para que con el wrapper que yo hice trate de crearse algo con CRM32Pro pero desde C# directamente haber que tal va...
Solo por el echo de realizar una prueba...

Si alguien se ofrece el el mismisimo TheAzazel quiere probar C#, ofresco el port...

P.D: Solo esta "wrappeado" CRM32Pro_ILogSystem y todas sus funciones (Init, Msg, DumpSurface, GetState, ProfileBegin, ProfileEnd y ProfileShow)
Vamos, que si este wrapper precario que me arme funciona tendria el wrapper total en unos 2 dias a mas tardar... Asi que eso...

Desenme suerte! Y haber quien se ofrece para hacer la prueba! (si se necesita portar alguna otra funcion para hacer la prueba despues lo vemos...)


Gezequiel

 Eh tenido unos problemas, haber quien me ayuda...

El codio que trate de implementar para portar lo mas fundamental de CRM32Pro.dll (ILodSystem segun TheAzazel) seria algo por el estilo:
Citar
using System;
using System.Runtime.InteropServices;

namespace CRM32ProWrapper
{

   public class CRM32Pro_ILogSystem
   {
  [DllImport("CRM32Pro.dll", EntryPoint = "CRM32Pro_ILogSystem.Init")]
    public static extern void Init (char *  filename, char mode, char level, char * prgname, char * author, char * email, char * web);
 
     [DllImport("CRM32Pro.dll", EntryPoint = "CRM32Pro_ILogSystem.Msg")]
    public static extern void Msg (char  level, char * format);
 
     [DllImport("CRM32Pro.dll", EntryPoint = "CRM32Pro_ILogSystem.DumpSurface")]
    public static extern void DumpSurface (SDL_Surface * surface);
 
     [DllImport("CRM32Pro.dll", EntryPoint = "CRM32Pro_ILogSystem.GetState")]
    public static extern byte GetState ();
 
     [DllImport("CRM32Pro.dll", EntryPoint = "CRM32Pro_ILogSystem.ProfileBegin")]
    public static extern void ProfileBegin (char * name);
 
     [DllImport("CRM32Pro.dll", EntryPoint = "CRM32Pro_ILogSystem.ProfileEnd")]
    public static extern void ProfileEnd (char *name);
 
     [DllImport("CRM32Pro.dll", EntryPoint = "CRM32Pro_ILogSystem.ProfileShow")]
   public static extern void ProfileShow ();
   }
}

Lo que pasa es que me salen errores como:

a)Referenciando a la libreria, me pone:
fatal error CS0009: No se puede abrir el archivo de metadatos -- No existen metadatos en la memoria o secuencia

b)Sin reerenciar a la libreria me pone:
No se puede encontrar el tipo o el nombre de espacio de nombres 'SDL_Surface' (¿falta una directiva using o una reerencia de ensamblado?)

Haber si alguien me da una mano, que haciendolo en C# se me solucionarian varios problemas, y como dije, en don dias ya tendria todo el wrapper echo (suponiendo que hacer el resto de la lib no traeria errores y seria escribir el resto del codgo como al principio)

BeRSeRKeR

 Bueno, hay unos problemas con ese wrapper que estás intentando hacer. Primero, estás utilizando tipos de datos unmanaged (char *) cuando tendrías que utilizar el equivalente en managed, que es string.

Luego está el tema de la forma en la que estás especificando los puntos de entrada de los métodos de la clase ILogSystem. De esa forma, C# no va a ser capaz de encontrarlos ya que la dll no los expone así.

Yo creo que no se puede llevar a cabo el wrapper de una DLL en C++ a través de C#. Puedo estar equivocado pero por las cosas que he visto, no hay indicios de que se pueda. Que no digo que sea imposible, pero yo no he visto nada que indique lo contrario. Así que la forma de llevar a acabo dicho wrapper es a través de managed C++ y evidentemente no te vas a librar de ciertas complicaciones pero creo que es la forma más directa.

Por ejemplo, yo he hecho el envoltorio para las clases CRM32Pro_ILogSystem y CRM32Pro_IStuffDPF pero no están del todo implementadas.

La clase CRM32Pro_ILogSystem parece funcionar perfectamente excepto el método DumpSurface que tiene como parámetro de entrada una superficie de SDL. Evidentemente este es un tipo unmanaged y habría que hacerlo managed. Una opción sería utilizar alguna implementación managed de SDL (si es que existe).

Luego, la clase CRM32Pro_IStuffDPF también está casi implementada pero nos encontramos con la estructura DPF_BlockData que tiene arrays de longitud fija y un puntero a un buffer de datos. Eso habría que convertirlo a managed. Sé que hay atributos para poder especificar arrays de longitud fija pero no recuerdo cuáles son ahora mismo. Y bueno, el puntero a un buffer se podría tratar como IntPtr y luego me imagino que habría que tener un método para convertir la estructura a unmanaged y viceversa. El caso es que he probado a crear un DPF (en la aplicación cliente en C# que he creado para ir probando el wrapper) y efectivamente lo crea (se escribe la cabecera), pero hasta que no se pase la estructura a managed, no se podrían insertar bloques de datos y demás operaciones posibles.

Le he echado un vistazo rápido al archivo de cabecera de CRM32Pro y te diré las cosas que me parece a mí que te traerán más problemas a la hora de ser implementados.

  • Estructuras con arrays de tamaño fijo y punteros a buffers.
  • Punteros a SDL_Surface. Por suerte parece que junto con SDL_Rect es el único tipo de las SDL que utiliza CRM32Pro (al menos que se exponga).
  • Punteros a funciones. Por ejemplo la función que se llamará al pulsar un botón del ratón. En managed esto se resuelve con delegates.
  • Ciertas variables y funciones externas (que no son posibles en managed de la misma forma que en C o C++) como screen, mouse_xpos, mouse_ypos, etc.
En fin, creo que esos son los puntos más peliagudos a la hora de crear el wrapper. Si superas eso, el resto será pan comido. En cualquier caso si alguien arroja luz sobre esos puntos, la cosa será más sencilla. Yo ahora mismo estoy liado creando contenido para Haddd así que mucho no podré hacer pero si tengo algún hueco y esto sigue adelante tal vez podría echar una mano.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Vicente

 Hola,

yo he encontrado dos ports de SDL a .NET:

Port 1

Port 2

No los he podido mirar y a lo mejor googleando más rato se encuentran más cosas, pero podría ayudar seguramente. Un saludo!

Vicente

TheAzazel

 Muchas gracias Berserker por ayudar... la verdad es que he visto y probado el wrapper que has hecho de Ilogsystem y pinta muy muy bien :P y gracias tambien por echar un cable a gezequiel  (ole)
Por cierto, cuando dije lo de "la intefaz mas facil de wrappear seria ILogSystem" me referia solo al miembro Init...puesto que el Msg telita con los argumentos variables pero ya he visto que has pasado por encima de ellos jeje

Voy a intentar aportar mi granito...

@Gezequiel: en los links de este mismo thread(algunos los puse yo, otros los pusieron los habituales del foro) ponia claramente lo que Berserker intuye: no se puede hacer un wrapper de una DLL escrita en C++ unmanaged directamente sobre C#. Concreto, lo que no se puede hacer es wrappear clases. Luego si el codigo de CRM32Pro fuera C o C++(sin utilizar clases) se podria importar y wrappear tal y como lo has intentado hacer tu. Luego, yo no perderia mas tiempo con ello(intentando hacerlo en C# directamente), el camino correcto es el dado por Berserker(el link que te puse, hacen lo mismo que ha hecho el).
Ah, y todas las pruebas que necesites que alguien te haga... por supuesto cuenta conmigo, me lo mandas por email y lo pruebo en cuanto lo vea y te cuento (el email esta en la web... que viene a ser megastorm(ARROBA)mi.madritel.es).

@Berserker: sobre los puntos que estimas con posibles problemas, puedo resolver algunos y otros no se como hacerlo:
Citar
1.- Estructuras con arrays de tamaño fijo y punteros a buffers.
2.- Punteros a SDL_Surface. Por suerte parece que junto con SDL_Rect es el único tipo de las SDL que utiliza CRM32Pro (al menos que se exponga).
3.- Punteros a funciones. Por ejemplo la función que se llamará al pulsar un botón del ratón. En managed esto se resuelve con delegates.
4.- Ciertas variables y funciones externas (que no son posibles en managed de la misma forma que en C o C++) como screen, mouse_xpos, mouse_ypos, etc.

El punto 1 no sabria como resolverlo(no se C#) pero quizas alguien, aparte de la informacion que das, pueda ayudar para aclarar del todo esto.

El punto 2... tal y como dices...esas dos son las unicas estructuras que CRM32Pro expone.. internamente utiliza mas pero de cara hacia fuera da igual. (Aqui se podria utilizar algun port de SDL a Net para ver como han convertido esas estructuras a managed).

El punto 3...si tu dices que es con delegates...te creo jejeje, yo no tengo ni idea de C# a ese nivel jejeje

Y finalmente, el 4, aqui no hay que preocuparse puesto que para la version que esta llegando, todas las variables/funciones globales van a desaparecer y pasaran a formar parte de una interfaz.


@Vicente: desde luego que esos dos ports ayudaran.... el primer paso seria realizar un wrapper de CRM32Pro pero tambien hay que wrappear luego todas las funciones de SDL, y para esto(que es mas facil al ser codigo C) se puede uno fijar en estos dos wrappers y como lo han hecho.


Resumiendo:

- Wrapper en C++ managed de CRM32Pro (permitira su uso en cualquier .NET)
- Resolver esos puntos indicados por Berserker
- Utilizar los port a NET de SDL para obtener las estructuras SDL_Surface y SDL_Rect en formato managed.
- Importar las funciones y datos de SDL a managed o utilizar el port existente.

Saludos

Haddd

 ¿y hacerlo en C# desde 0 ? No es difícil, el motor lo empecé a hacer sin tener ni idea de C#  ;)  

Vicente

 Hola,

mirando un poco más por internet (respecto al tema de los arrays de tamaño fijo). Creo que el atributo es este:

[MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]

Parece ser que tiene algo como SizeConst que es para especificar el tamaño del array. La info está sacada de:

MSDN

No lo he podido leer mucho (toy en el curro). Espero que ayude ;) Un saludo!

Vicente

Edit: Acabo de encontrar esto

Fixed-Size Buffers

C# 2.0 expanded the use of the fixed keyword to enable you to create fixed-sized, single-dimension arrays, which are called fixed-size buffers. A fixed-size buffer is always a member of a struct. The purpose of a fixed-size buffer is to allow the creation of a struct in which the array elements that make up the buffer are contained within the struct. Normally, when you include an array member in a struct, only a reference to the array is actually held within the struct. By using a fixed-size buffer, you cause the entire array to be contained within the struct. This results in a structure that can be used in situations in which the size of a struct is important, such as in mixed-language programming; interfacing to data not created by a C# program; or whenever a non-managed struct containing an array is required. Fixed-size buffers can only be used within an unsafe context.

Sale de aquí.

Gezequiel

 Cuanta info junta!!
Parece entonces que va a tener que ser directamente en C++.Net :( .
Lamentablemente eso no es lo mio, pero vamos a ver que sale...

Bueno, como primer paso, me estoy descargando el C# 2005, que parece que con mi framework 1.1 estaba un poco desactualizado... :D

Segundo, ya voy a ponerme a leer lo de "Estructuras con arrays de tamaño fijo y punteros a buffers." y otro poco de delegates.

Tercero, para hacer el wrapper, tendrian que hacerse "llamadas" a los metodos de la libreria desde managed, estoy en lo cierto??

Haddd: Me encantaria poder portar toda la libreria directamente a C# (genial) , pero vamos, que si no puedo con unos pasos en C++ unmanaged a managed, toda la libreria se complicaria bastante (nooo) ... Ademas quien sabe, quisas TheAzazel no quiera que se haga eso, y solo este buscando un wrapper para luego hacerlo el, quien sabe ;) .

Bien, creo que por ahora eso es todo, me gusta esto de abrir mi firefox en Stratos y encontrarme con kilos de informacion...
En todo caso edito o agrego otro post si no me deja... :ph34r:  

Gezequiel

 Recien acabo de recordar que hace un tiempo, cuando me disponia a hacer el port de CRM32Pro yo solo (pobre ingenuo :P ) le mande un mail a un podriamos decir "Guru" de la programacion en C# y C++ de aqui de argentina, asi que abri mi Gmail y me puse a buscar el mail, una vez encontrado descubri que si existe una forma de portar la lib a C#, pero que seria muy extenso.
Les copio el mensaje para que vean:

CitarHola, Gaston, mirá el tema de las dlls desde C# es un tema. Si la dll hecha en C++ sólo posee funciones globales (sin clases) hay que hacer una clase C# que invoque cada uno de sus métodos. El tema es si la DLL posee clases (lo cual es bastante común), en dicho caso se complica un poco y es necesario realizar una clase con bastante código para poder hacer uso de la librería (a tal punto que en una ocasión cuando tuve que hacerlo preferí reescribir la DLL).

Si la lib tiene clases y tenés el código fuente de la DLL tal vez te convenga recompilarla en Managed C++ (igual tendrás que hacer algunos cambios)

Jeje, parece que Haddd no estaba tan confundido respecto a lo de crear la Lib directamente el C# otra vez!! :D . Sin embargo parece que con el codigo fuente podria recompilarse y haci hacerlo mas sencillo... o quisas no... jeje XD
Quisas alguien con el Visual Studio podria recompilarlo y pasarlo a Managed para ver si esa alternativa funciona

BeRSeRKeR

 Está claro que lo mejor es reescribir la dll directamente en managed (cualquier lenguaje administrado). Pero en el caso de que eso no fuera posible, lo mejor es hacer el wrapper en managed C++. El mismo programador al que escribiste lo dice, es muy complicado desarrollar el wrapper en C# para una dll en C++ (y no sabemos el impacto en el rendimiento que tendría).

En, cuanto a recompilar la dll pero en managed C++, no sólo sería recompilar. Habría que hacer bastantes cambios para convertir todos los tipos de datos a managed y otras cosas como el uso de delegates (que no es que sea complicado). En fin, te encuentras con los mismos puntos "calientes" que he mencionado en el mensaje anterior.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.