Iniciar Sesión

Ver la Versión Completa : [PowerCOBOL] CALL de cualquier DLL sin *.LIB ni "LoadLibrary"


Kuk
25 de agosto de 2015, 20:49
Amigos, he descubierto esto para el PowerCOBOL v3 y funciona en la version 9 tambien!!! :apl:

Cuando queremos llamar una DLL y no tenemos la LIB, simplemente hay que:


Crear un fichero de texto y llamarlo COBOL85.CBR
Dentro escribir el nombre del Form desde el que se va a llamar y .ENTRY
Nombres de las funciones = los nombres de las DLL-s correspondientes


Por ejemplo:


[MainForm.Entry]
FtpConnect=FTP.dll
FtpDisconnect=FTP.dll
LogIn=Protocol.dll
InvalidateRect=User32.dll


En el código debemos llamar estas funciones en dinámico, es decir por variable:


ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 FUNC PIC X(20).
01 hWnd PIC S9(9) COMP-5.
PROCEDURE DIVISION.

MOVE "hwnd" OF POW-SELF TO hWnd
MOVE "InvalidateRect" TO FUNC

CALL FUNC WITH STDCALL USING BY VALUE hWnd
BY VALUE 0
BY VALUE 1



¡¡¡Listo!!! :cerv:

Hrmcobol
30 de junio de 2016, 21:12
Genial Kuk, voy a probarlo y te cuento.

Resulta que yo puse en el buscador del foro el texto "DLL" y no me trajo ningún tema,
supongo que estaré buscando mal.

Josber
1 de julio de 2016, 08:07
Resulta que yo puse en el buscador del foro el texto "DLL" y no me trajo ningún tema,
supongo que estaré buscando mal.

Las búsquedas en el foro, han de tener más de 3 carácteres, de lo contrario no funcionan bien, porque el buscador las "toma" como palabras de uso frecuente, (por ejemplo tipo a los artículos el la los las, etc.

Un saludo.-

Hrmcobol
19 de julio de 2016, 23:17
Estimado Kuk, no doy "pieconbola" la dll se llama MLUSER32.DLL y debo hacer un call a: "mluser" que tiene 5 parámetros numéricos.
Si no te molesta podrías mandarme el código y el cobol85.cbr, ya que no tengo experiencia en este tipo de llamadas.
Saludos

Kuk
20 de julio de 2016, 08:38
Hrmcobol, en tu COBOL85.CBR, al final del fichero debe añadir (cambiando MainForm por el nombre del Form que va a llamar la DLL):


[MainForm.Entry]
mluser=MLUSER32.DLL


En el Form que llama la DLL pones:


ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 FUNC PIC X(20).
01 NUM1 PIC S9(9) COMP-5.
01 NUM2 PIC S9(9) COMP-5.
01 NUM3 PIC S9(9) COMP-5.
01 NUM4 PIC S9(9) COMP-5.
PROCEDURE DIVISION.

MOVE "mluser" TO FUNC

CALL FUNC WITH STDCALL USING BY VALUE NUM1
BY VALUE NUM2
BY VALUE NUM3
BY VALUE NUM4


Debes poner MLUSER32.DLL en el mismo directorio que tu programa PowerCOBOL.

Si no te sale aún, dime más concretamente qué es exactamente lo que no logras hacer :)

Hrmcobol
26 de julio de 2016, 19:24
Amigo Kuk, te adjunto la DLL La LIB, quiero hacer un call a "mluser", te adjunto un VB por si tu puedes abriro, este vb funciona correctamente, podras mirlo un poco
Saludos

Kuk
27 de julio de 2016, 23:14
Hrmcobol, me pillas más liado que nunca amigo... Voy a mirar si puedo mirarlo la semana que viene, antes no creo que pueda...

Hrmcobol
29 de julio de 2016, 22:23
Estimado kuk, resolví a medias el tema de la DLL, ya puedo acceder a la misma, el problema era el de siempre, uno mira y no ve, tenia mal escrito los parámetros.
Gracias como siempre.
Los Mantengo al tanto a medida que resuelva todo

Hrmcobol
30 de julio de 2016, 01:43
PROBLEMA RESUELTO !! !! !!!

GRACIAS KUK POR EL POST !!!

Kuk
1 de agosto de 2016, 23:42
resolví a medias el tema
Dinos la resolución completa, por si alguien tiene el mismo problema. ;)

Hrmcobol
3 de agosto de 2016, 20:32
Estimados adjunto las lineas finales de la llamada
Mi problema era que definía mal las variables NUMX ya que no conocía/entendía/etc la declaración BINARY-SHORT / BINARY-LONG


ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 FUNC PIC X(20).
01 ReturnValue PIC S9(04) COMP-5.

77 NUM1 USAGE BINARY-SHORT SIGNED. *> Variable Short la rutina programada en "C"
77 NUM2 USAGE BINARY-SHORT SIGNED.
77 NUM3 USAGE BINARY-LONG SIGNED. *> Variable Long la rutina programada en "C"
77 NUM4 USAGE BINARY-LONG SIGNED.
77 NUM5 USAGE BINARY-SHORT SIGNED.

PROCEDURE DIVISION.

MOVE "mluser" TO FUNC
MOVE 1 TO NUM1
MOVE 1 TO NUM2
MOVE 1000 TO NUM3
MOVE -1800027647 TO NUM4
MOVE 0 TO NUM5
MOVE ZEROS TO ReturnValue

CALL FUNC WITH STDCALL LINKAGE
USING BY VALUE NUM1
BY VALUE NUM2
BY VALUE NUM3
BY VALUE NUM4
BY VALUE NUM5
RETURNING ReturnValue
END-CALL

IF ReturnValue = ZEROS Display "Correcto"
ELSE Display "Error Numero: " ReturnValue
END-IF



El Archivo COBOL85.CBR


[F-009001.Entry] <--- Nombre del Form que llama la Dll Exterma -> F-090001
mluser=MLUSERXX.DLL <--- La Dll externa se llama -> MLUSERXX.DLL
FtpConnect=MLUSERXX.dll <---
FtpDisconnect=MLUSERXX.dll <---
LogIn=Protocol.dll
InvalidateRect=User32.dll


Tal cual lo describio KUK en el inicio del post

Saludos y Gracias Por Estar Alli !!!!

Recato53
4 de febrero de 2017, 11:47
Buenos días.

Quiero comprobar si existe conexión a internet.
He probado todo las opciones que he encontrado en el Foro, algo estoy programando mal.
Intento usar COBOL85.CBR y desde el programa de PowerCobol llamo a la función. Pero responde con u mensaje de ERROR.

Hrmcobol, en tu COBOL85.CBR, al final del fichero debe añadir (cambiando MainForm por el nombre del Form que va a llamar la DLL):


[MainForm.Entry]
mluser=MLUSER32.DLL


En el Form que llama la DLL pones:


ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 FUNC PIC X(20).
01 NUM1 PIC S9(9) COMP-5.
01 NUM2 PIC S9(9) COMP-5.
01 NUM3 PIC S9(9) COMP-5.
01 NUM4 PIC S9(9) COMP-5.
PROCEDURE DIVISION.

MOVE "mluser" TO FUNC

CALL FUNC WITH STDCALL USING BY VALUE NUM1
BY VALUE NUM2
BY VALUE NUM3
BY VALUE NUM4


Debes poner MLUSER32.DLL en el mismo directorio que tu programa PowerCOBOL.

Si no te sale aún, dime más concretamente qué es exactamente lo que no logras hacer :)

Adjunto ejemplo del programa.

Kuk
4 de febrero de 2017, 12:24
Amigo Recato53, el fichero COBOL85.CBR lo tienes que poner en el mismo directorio que el ejecutable (en la carpeta mi_projecto\DEBUG), si no lo haces no va a funcionar. El ejecutable cuando arranca, por medio del Run-Time se busca el fichero COBOL85.CBR en el mismo directorio, y la lista de ENTRY-s que hay en realidad se cargan vía "LoadLibrary" y "GetProcAddress" pero se hace por el Run-Time y no por nosotros.

Recato53
4 de febrero de 2017, 12:47
Amigo Recato53, el fichero COBOL85.CBR lo tienes que poner en el mismo directorio que el ejecutable (en la carpeta mi_projecto\DEBUG), si no lo haces no va a funcionar. El ejecutable cuando arranca, por medio del Run-Time se busca el fichero COBOL85.CBR en el mismo directorio, y la lista de ENTRY-s que hay en realidad se cargan vía "LoadLibrary" y "GetProcAddress" pero se hace por el Run-Time y no por nosotros.
Pongo el fichero en donde me dices y sigue dando el mismo error.

Kuk
4 de febrero de 2017, 15:10
Recato53, también tienes mal escrito el nombre de la función InternetCheckConnectionA en el fichero COBOL85.CBR. Tienes InternetcheckConnectionA en vez de InternetCheckConnectionA, en caso de rutinas C y WinAPI las minúsculas/mayúsculas importan. ;)

Recato53
5 de febrero de 2017, 21:34
Muchas gracias KUK.

Por fin funciona la rutina para testear si hay conexión a internet.

Si llamo a este programa (.exe) desde un programa en PowerCobol(.DLL), como recupero el valor en el programa de PowerCobol.

Kuk
6 de febrero de 2017, 10:07
Recato53, ¿por qué lo quieres hacer como un EXE? Haz una simple rutina COBOL y a llamas donde la necesites.

Pero si quieres hacerlo como dices, y no quieres que sea un DLL sino un EXE... :piensa: Puedes intentar hacer un MOVE al RETURN-CODE en el EXE, y en el programa llamante recibes dicho valor en el campo RETURNING. Pruébalo y nos cuentas.

Recato53
9 de febrero de 2017, 16:44
Recato53, ¿por qué lo quieres hacer como un EXE? Haz una simple rutina COBOL y a llamas donde la necesites.

Pero si quieres hacerlo como dices, y no quieres que sea un DLL sino un EXE... :piensa: Puedes intentar hacer un MOVE al RETURN-CODE en el EXE, y en el programa llamante recibes dicho valor en el campo RETURNING. Pruébalo y nos cuentas.

Buenas tardes.
La estructura de carpetas que empleo en mis aplicaciones es la siguiente:

\Aplicación
\Aplicación\Datos
\Aplicación\Programas (aquí están todas las 'dll' , 'exe' y archivos necesarios para ejecutar la aplicación).

El programa que ejecuta la aplicación esta en \Aplicación\Aplicacion.exe

Desde una 'dll' llamo a la rutina que quiero comprobar si hay conexión a Internet.

Como el archivo COBOL85.CBR tiene que estar en la misma carpeta del programa que llama a esta rutina, necesito recuperar el valor en la DLL que resulta de llamar a la rutina 'exe'.

Según me indicas puedo programar RETURN-CODE y recogerlo con RETURNING, me puedes hacer llegar un ejemplo, no consigo que esto me funciones.

Muchas gracias.
Un saludo.

Kuk
9 de febrero de 2017, 17:07
Recato53, a ver, no me estoy enterando de cual es el problema con el COBOL85.CBR. Puede haber varios por aplicación, pero sólo 1 por directorio. Es decir, puedes tener uno en \Aplicación\ y otro \Aplicación\Programas\.

Así que:


El fichero COBOL85.CBR tiene que estar en \Aplicación\Programas\ (donde está el programa Comprueba_Conexion.exe).
Aplicacion.exe va a llamar a \Aplicación\Programas\DLL-1
DLL-1 va a llamar al Comprueba_Conexion.exe


En cuanto lo que dije sobre el RC, me he equivocado, no va a ser posible, porque estamos en mundo GUI y hay subrutinas que se ejecutan después de salir del código COBOL. Pero tengo una idea y te la voy a explicar en un tema separado ;)

Recato53
29 de julio de 2017, 20:11
Kuk, Estoy desarrollando una rutina para pasar un archivo TXT, de ANSI a UTF-8 y viceversa cuando la tenga acabada y documentada, donde la tengo que cargar en el FORO.

Un saludo.

Kuk
29 de julio de 2017, 23:33
Recato53, pues en alguno de los subforos "Cocina". Si esa rutina es genérica e independiente del compilador, cuélgala en el subforo "Cocina" general. Si no, dependiendo del compilador que hayas usado (y tecnología, como COM o WinAPI) la cuelgas en el correspondiente. Eso sí, creando un tema nuevo. ;)