Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 16-02-2004
jsb jsb is offline
Registrado
 
Registrado: sep 2003
Posts: 8
Poder: 0
jsb Va por buen camino
Question Parametros entre Delphi i c++ Builder

Hola muy buenas a todos/as!!!

Necesitaria si alguien tiene como pasar como parametro "records" entre una dll hecha en C++ (structs) y un programa que llama a la dll en delphi . Intento pasarlo utilizando packed records en el lado delphi i structs en la parte de c++, lo he intentado con punteros pero no consigo que a la dll le lleguen los valores correctos ni que la dll retorne valores. Muchas gracias!!
Responder Con Cita
  #2  
Antiguo 16-02-2004
cht666cht cht666cht is offline
Miembro
 
Registrado: nov 2003
Posts: 14
Poder: 0
cht666cht Va por buen camino
Para esto creo que deberías usar File Mapping, que te permite compartir una zona de memoria entre distintos procesos. Mira en la ayuda que viene con Delphi (Win32 Programmer's Reference).
Un saludo.
Responder Con Cita
  #3  
Antiguo 17-02-2004
jsb jsb is offline
Registrado
 
Registrado: sep 2003
Posts: 8
Poder: 0
jsb Va por buen camino
Unhappy problemas con parametros

Muchas gracias por responder cht666ch.
Pero he estado mirando la ayuda que me dices, y lo del file Mapping es para cuando hay mas de un proceso atacando contra un mismo fichero. Yo el problemas lo tengo con un unico proceso.

Estoy creando un editor de vrml, en el que el motor grafico i el parser ,estan en una dll ( que estoy desarrollando en C++ Builder 6.0) , en cambio la interficie del editor la estoy desarrollando en Delphi 5.0 , y desde la interficie se carga la dll y hago llamadas afunciones que exporto de la dll, con todas las funciones com parametros simples no hay problema, pero ahora mew he visto con la necesidad de pasar parametros de tipo Struct o record entre la interficie y la dll, pero ni a la dll le llegan el record con los valores que le paso a la dll , ni la dll devuelve los valores modicados. Yo me temo que no sea alguna opción del project.

De todas maneras muchas gracias. Si piensas que me equivoco en algo no dudes en decirmelo.
Responder Con Cita
  #4  
Antiguo 17-02-2004
cht666cht cht666cht is offline
Miembro
 
Registrado: nov 2003
Posts: 14
Poder: 0
cht666cht Va por buen camino
Recuerdo haber probado alguna vez también de pasar punteros como parámetros en funciones de DLLs y tener los mismos problemas que tu dices, por lo que creo que el código de la DLL y el de el EXE no se cargan en el mismo espacio de memoria. Yo he usado el File Mapping para compartir records entre dos EXEs pero creo que funcionaria igual entre un EXE y una DLL. Haz una prueba, no es muy complicado de usar y tampoco se me ocurre otro sistema.
Responder Con Cita
  #5  
Antiguo 18-02-2004
jsb jsb is offline
Registrado
 
Registrado: sep 2003
Posts: 8
Poder: 0
jsb Va por buen camino
Question Problemas con parametros

Hola muy buenas cht666cht, me he decidido a provar lo de File Mapping, y me encuentro con problemas debido a mi desconocimiento de estos metodos. A ver

Yo desde Delphi , cargaba la libreria del modo

Handler := LoadLibrary(Pchar('Parser.dll'))

y luego para llamar a los metodos de la dll ,por ejemplo

@IniciaGL := GetProcAddress(Handler,PChar('IniciarGL'));
if @IniciaGL <>nil then
IniciaGL(FTop.Handle,C_TOP);

donde IniciaGl es una variable del tipo procedure con la misma estructura que tenga la función en la dll.

Hasta aqui es como yo vengo utilizando la dll, i en esta manera de funcionar en donde tengo problemas a la hora de pasar records.

He estado mirando el help que me dijiste i deversa documentación en internet i he creado un fileMapping de la siguiente manera

Hfitxer := CreateFile(Pchar('Parser.dll'),GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
Handler := CreateFileMapping(Hfitxer,nil,PAGE_READWRITE,0,0,MAPNAME);

Pero hasta aqui bién , pero al hacer un GetprocAddress(Handler,'XXXXX') no encuentra ninguna función, en que he cometido el error?

Supongo que el error debe ser de concepto, y te agradezco tu paciencia conmigo ya que este tema para mi es del todo novedoso.

Muchas gracias por adelantado!!!
Responder Con Cita
  #6  
Antiguo 19-02-2004
cht666cht cht666cht is offline
Miembro
 
Registrado: nov 2003
Posts: 14
Poder: 0
cht666cht Va por buen camino
Mira, he estado mirando el código que utilicé para compartir un record entre dos aplicaciones. Básicamente seria algo asi:

1.
Tanto en el EXE como en la DLL has de declarar el mismo record en el que estará la información que quieres compartir:

type

TDatos = packed record
a, b, c: Integer;
end;
PDatos = ^TDatos; // el tipo PDatos será un puntero a un TDatos

y una variable para acceder al mismo:

var
Datos: PDatos;


2.
El siguiente paso es reservar la memoria, y eso lo ha de hacer o el EXE o la DLL, en una funcíón de inicialización, en el OnCreate o donde lo creas conveniente:

FileMappingObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TDatos), 'IDENTIFICADOR_DEL_FILEMAPPING');
Datos := MapViewOfFile(FileMappingObject, FILE_MAP_ALL_ACCESS, 0, 0, 0);
Mutex := CreateMutex(nil, False, 'IDENTIFICADOR_DEL_MUTEX');

También se crea un mutex, que es el objeto mediante el cual sincronizaremos el acceso a la memoria. recuerda declarar las variables 'FileMappingObject' y 'Mutex' , de tipo THandle.

y para liberar la memoria y el mutex:

CloseHandle(Mutex);
UnmapViewOfFile(Datos);
CloseHandle(FileMappingObject);

Esto en la funcion de finalización, en el OnDestroy, etc...

3.
En el resto de procesos que vayan a acceder a esa zona de memoria, obtendras el puntero y el identificador del mutex asi:

FileMappingObject := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'IDENTIFICADOR_DEL_FILEMAPPING');
Datos := MapViewOfFile(FileMappingObject, FILE_MAP_ALL_ACCESS, 0, 0, 0);
Mutex := OpenMutex(SYNCHRONIZE, True, 'IDENTIFICADOR_DEL_MUTEX');

o sea, que si el paso 2 lo has hecho en la DLL, en el EXE tendrás que hacer esto.

usa el mismo codigo del paso 2 para liberar los objetos.

4.
Ahora ya puedes acceder a la estructura 'Datos' tanto desde el EXE como de la DLL. Para eso utiliza este código:

// esperar hasta tener acceso
if WaitForSingleObject(Mutex, INFINITE) <> WAIT_FAILED then
begin
// aqui se puede trabajar con 'Datos'
...
// al final liberar el mutex para que otro proceso pueda acceder
ReleaseMutex(Mutex);
end;

Esto es todo, espero que te sirva para lo que necesitas.
Un saludo.
Responder Con Cita
  #7  
Antiguo 19-02-2004
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 28
jachguate Va por buen camino
Lamento llegar un poco tarde... pero quiero apuntar que si es posible pasar y recibir estructuras (records) en los parámetros de llamadas a rutinas de una DLL escrita en otro lenguaje. Basta con ver las llamadas al API de windows que se hacen desde Delphi.

Lo que hay que tener en cuenta, es el esquema de paso de parámetros (calling convention) que se utilizará. Si las rutinas están escritas en C/C++ yo te recomiendo usar stdcall (verificando que la dll sea construida respetando esta convención).

Cita:
Empezado por La ayuda de delphi
The default calling convention is register, but interfaces shared among modules (especially if they are written in different languages) should declare all methods with stdcall. Use safecall to implement methods of dual interfaces and CORBA interfaces.
For more information about calling conventions, see Calling conventions.
Otro asunto a tener en cuenta... es si los datos en el registro estarán alineados en memoria (una estructura optimizada para su acceso por el CPU) o no. Si los registros no vienen alineados... declarar los tipos como packed record en delphi.

Cita:
Empezado por La ayuda de delphi
When a record type is declared in the {$A+} state (the default), and when the declaration does not include a packed modifier, the type is an unpacked record type, and the fields of the record are aligned for efficient access by the CPU. The alignment is controlled by the type of each field. Every data type has an inherent alignment, which is automatically computed by the compiler. The alignment can be 1, 2, 4, or 8, and represents the byte boundary that a value of the type must be stored on to provide the most efficient access. The table below lists the alignments for all data types.
.

Por último... aunque es algo básico, verificar si los parámetros se están pasando por referencia...

hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate

Última edición por jachguate fecha: 19-02-2004 a las 17:48:15.
Responder Con Cita
  #8  
Antiguo 20-02-2004
jsb jsb is offline
Registrado
 
Registrado: sep 2003
Posts: 8
Poder: 0
jsb Va por buen camino
Smile Problemas con parametros

Hola muy buenas cht666cht he seguido todos tus pasos y funciona con normalidad, una ultima consulta si tengo X diferentes records , he de realizar lo del FileMapping para cada uno de ellos? si,verdad?.

Bueno solo me queda darte de verdad muchas grácias por tu ayuda, y si tienes alguna consulta en la que te pueda ayudar , no dudes en preguntarme. Muchas gracias.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 20:42:42.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi