Tipos de Usuario.

02/06/2005 - 09:08 por Vas | Informe spam
Hi grupo, haber si me podeis hechar una mano. Estoy
migrando una aplicación de delphi a C# y me he encontrado
con una "chorrada" que me ha dejado un poco afuscado.
Tengo una librería externa para la cual me he creado una
clase implementando las llamadas externas a través
de "dllimport", y en su versión delphi ténía definido 3
tipos de usuario con arrays tipo "char".

Pues bien, no he encontrado forma "decente" de crear
tipos "similares" en c#, algo tan sencillo como tener una
constante tipo int que guarda el tamaño del array y un
tipo de usuario que dimensiona un array tipo char con la
longitud de la constante, algo así:

constante "nombre" = 256;
tipo "nombretipo" = array [1..constante] de char.

Bueno, espero no haber sido muy "chapas" en la exposición
y si alguien tiene alguna idea, gracias de antemano.

PD: Actualmente lo he resuelto de una manera
bastante "chapucera", pero bueno.

Preguntas similare

Leer las respuestas

#6 vas
06/06/2005 - 18:40 | Informe spam
Hi Octavio:

Despues de realizar distintas pruebas, y debido a que
estoy dando palos de ciego con esta história debido a mis
conocimientos sobre este aspecto en C#, no he conseguido
hacerlo "chutar". Si se te ocurre alguna cosa más, te
estaré muy agradecido, además de agradecerte tu atención
ya prestada.

Estoy por currarme la "interface" en delphi solo con las
funciones necesarias y linkarlo desde C#, ya que la Dll
que estoy utilizando es de una empresa que ya no existe,
por lo que no tengo posibilidad de ponerme en contacto
contacto con ellos.

La definición que tengo hecha en Delphi para atacar a la
citada Dll, por poner un ejemplo (son unas 200) es así:

procedure PI_OpenValidIndexBase
(IBS:IBSType;IndexBaseName:PChar;SeatNumber:LongInt;Buffer:
Pointer;BufferSize:LongInt;UserID:LongInt;var
ErrorCode:LongInt);stdcall; far; external 'pi_w32.dll';

Donde IBS es un tipo de usuario tipo array de 3632 char
llenado por la Dll y que debe ser utilizado a posteriori
con el resto de llamadas, IndexBaseName es un PChar con la
ruta del fichero a abrir a suministrar a la dll,
SeatNumber es un valor fijo (-1), Buffer es un array de
20001 char, BufferSize es un valor fijo (19999), UserId
también valor fijo, y ErrorCode que es llenado también por
la dll.

Actualmente he creado dos estructuras como me has
comentado, pasandole los parámetros por valor y siempre
devuelve el error

"Excepción no controlada del
tipo 'System.NullReferenceException' en Test.exe

Información adicional: Referencia a objeto no establecida
como instancia de un objeto."

He probado a pasar los parámetros con "ref" y con "out" en
función del tipo de parámetro, pero sin resultados.
También he probado a dimensionar una estructura con un
array de char utilizando [MarshalAs
(UnmanagedType.ByValArray, SizeConst632)], consiguiendo
el mismo resultado.

Bueno, pues esa es mi "aventura", si se te ocurre algo...

Gracias de antemano y un saludo.

Vas
Perdona, vas, no me di cuenta de que quierías llamar la


DLL de Delphi desde
C#.
Te diré que el asunto es bastante complicado:

a) en Delphi un array es lo que en .NET diríamos un "tipo-


valor" que se
almacena en el lugar, y cuando lo pasas por valor se mete


en la pila el
array completo, y no un referencia, como ocurriría en C#.


Además en C# se
utiliza UNICODE para representar los caracteres y en


Delphi ASCII.

Para definir un tipo compatible con:

IBS5 = array [1..5] of char.

creo que tendrías que hacer esto:

[StructLayout(LayoutKind.Sequential, Pack=1)] // para


que los bytes queden
"pegaditos" en memoria
public struct IBS5 // estructura (tipo valor) y no clase


(tipo ref)
{
byte c1; // tantos como caracteres tiene el array


Delphi
byte c2; // no puedes usar el array de C#, que es


tipo-referencia
byte c3;
byte c4;
byte c5;
// constructor para simplificar el manejo
public IBS5(string s)
{
if (s.Length >= 1) c1 = (char) s[0] else c1 = 0;
if (s.Length >= 2) c2 = (char) s[1] else c2 = 0;
if (s.Length >= 3) c3 = (char) s[2] else c3 = 0;
if (s.Length >= 4) c4 = (char) s[3] else c4 = 0;
c5 = 0;
}
}

Para crear e inicializar con el valor 'Hola':

IBS5 hola = new IBS5("Hola");

Esto ya podrías pasarlo por valor como parámetro.

b) Debes tener en cuenta también que el convenio de paso


de parámetros
predeterminado en Delphi es 'register', que no es


estándar. Deberías
redefinir los métodos en Delphi utilizando la directiva


stdcall:

procedure Prueba(cadena: IBS5); stdcall;

y recompilar la DLL. Luego en en C# puedes indicar que


vas a utilizar el
convenio estándar de paso de parámetros mediante uno de


los argumentos del
atributo DllImport.

En C# 2.0 será más fácil esto, mira el siguiente artículo


de E. Gunnerson:




http://blogs.msdn.com/ericgu/archiv...13676.aspx

Salu2,

Octavio

"vas" escribió en el mensaje
news:0db601c56815$c7514080$
He intentado realizarlo convirtiendo las variables y tipos
delphi a los que creo que se deben utilizar en C#,
cambiando los "pchar" por "strings" los "LongInt"
por "long", etc, pero las llamadas a funciones de la
dll "petan". Os pongo la definición de una de la funciones
originales de delphi, haber si se os ocurre algo.

procedure PI_OpenValidIndexBase
(IBS:IBSType;IndexBaseName:PChar;SeatNumber:LongInt;
Buffer:Pointer;BufferSize:LongInt;UserID:LongInt;var
ErrorCode:LongInt);
stdcall; far; external 'pi_w32.dll';

Yo estoy utilizando para la "traducción" a C# las
definiciones basadas en "DllImport", cambiando sus
definiciones, como por ejemplo "IBSType" que es un array
de char en Delphi, yo lo cambio por "string", etc, aunque
con el tema de los punteros ando un poco perdido.

Bueno, os agradezco mucho vuestras respuestas una vez más,
y si teneis cualquier idea, pues agradecido de que la
compartais, un saludo, VAS.
VAS,

a) Esa definición de cadenas estilo Pascal viene de


tiempos en los que la
necesidad de economizar el espacio era grande. En C# y


otros lenguajes
modernos para representar cadenas se utiliza el tipo


String, sin necesidad
de indicar estáticamente cuál será la longitud máxima que


va a tener.

b) En C# cuando una función recibe un String le puedes


pasar una cadena de
la logitud que sea. Incluso si la función recibe un


array, no hay necesidad
de indicar la cantidad máxima de elementos que este podrá


tener:

public static void Main(string[] args) // no se


indica la dimensión
máxima !
{

Hay muchos cambios de filosofía que tendrás que asimilar.


En este caso
particular, estoy casi seguro de que esos tres tipos de


que hablas los
puedes eliminar sin peligro alguno...

Slds - Octavio

"Vas" escribió en el mensaje
news:090a01c56741$f0c1e020$
Hi grupo, haber si me podeis hechar una mano. Estoy
migrando una aplicación de delphi a C# y me he encontrado
con una "chorrada" que me ha dejado un poco afuscado.
Tengo una librería externa para la cual me he creado una
clase implementando las llamadas externas a través
de "dllimport", y en su versión delphi ténía definido 3
tipos de usuario con arrays tipo "char".

Pues bien, no he encontrado forma "decente" de crear
tipos "similares" en c#, algo tan sencillo como tener una
constante tipo int que guarda el tamaño del array y un
tipo de usuario que dimensiona un array tipo char con la
longitud de la constante, algo así:

constante "nombre" = 256;
tipo "nombretipo" = array [1..constante] de char.

Bueno, espero no haber sido muy "chapas" en la exposición
y si alguien tiene alguna idea, gracias de antemano.

PD: Actualmente lo he resuelto de una manera
bastante "chapucera", pero bueno.


.





.

email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida