Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Calling DLL from Fujitsu COBOL

Status
Not open for further replies.

Glenn9999

Programmer
Jun 19, 2004
2,312
US
Does anyone know the location of an example where you can call a DLL (not Windows, but yours!) from a Fujitsu COBOL program?
 
Fujistu has some samples included.

I'm not finding them. I looked through the ones I saw in the program directory and the manuals. But I'm using the very old (yet free) Fujitsu COBOL 3.0, so it might be possible that it's just simply not supported?
 
OK I got the WinAPI linkages lined out (they're not really DLL calls but LIB calls), and used those to start code on executing something in a DLL.

The last major hitch I see before me: Does Fujitsu COBOL 3.0 support procedure pointers and how?
 
Glenn.

In order to call a DLL you do link with the LIB, not the DLL. LIB's is the way compilers know what the DLL contains.


As for procedure points. do you have an example of what you are trying to do? i may install my old v3 just to see.

Regards

Frederico Fonseca
SysSoft Integrated Ltd
 
In order to call a DLL you do link with the LIB, not the DLL. LIB's is the way compilers know what the DLL contains.

This is incorrect. A LIB is a piece of code that is statically linked into the executable itself and has absolutely no association with the DLLs on the system, besides what the coder of the LIB did. For Fujitsu COBOL 3.0, it links KERNEL32.LIB and USER32.LIB.

These have nothing to do with DLLs on the system beyond the intent of Fujitsu (or Microsoft). As I understand it, these files are actually LIB versions of the DLLs that come in the Microsoft SDK.

Now functionally, anything in those LIB files is nothing different than what is linked through an OBJ file. This means in a calling program with a called program of "TEST1", CALL "GetCurrentDirectoryA" is nothing different than CALL "TEST1" to the compiler.

What is the difference for a DLL? The DLL can either be statically linked by the compiler, or dynamically loaded at run-time by programmer code. This means as a coder in Windows, one can load a DLL, locate a specific procedure/function, and then execute it - all nothing different than any other imperative statements.

This makes it all fully dynamic - the code for an application can be changed simply by updating a DLL. It also makes it possible to incorporate DLLs into logic. As an example, I'm working on a project (in another language) which lists all the DLLs in the same folder, and calls uniform routines within them. I can add and remove DLLs out of this folder at will, and the program will simply run whatever it finds.

As for procedure points. do you have an example of what you are trying to do? i may install my old v3 just to see.

In other languages, you can define a variable which can be addressed as a procedure pointer and executed in code as a statically-defined at compile time procedure.

A simple Delphi example.

Code:
program pp; uses empty_unit;
var
  c: procedure;

procedure a;
  begin
    writeln('Procedure A has run');
  end;

begin
  c := @a; { set procedure pointer to the address of the static procedure}
  c; { execute the procedure pointer }
end.

As for the DLL loading, I've got most of that done, the question before I can test the source is how to run the resulting procedure/function, which is returned as a procedure pointer.
 
Okay I think I've been pretty much convinced that the compiler doesn't support what I'm wanting to do (i.e. no procedure pointer support). I'll go ahead and post what I've done so it might help someone using another COBOL compiler (or a later version of Fujitsu if they added that option). But without a way to directly call the code in the procedure pointer, it's not going to work.

The called module I used, compiled and linked into a DLL. More for documentation purposes than anything.
Code:
000010 @OPTIONS NOMAIN
000020 IDENTIFICATION DIVISION.
000030 PROGRAM-ID. COBDLLTST.
000040 ENVIRONMENT DIVISION.
000050 INPUT-OUTPUT SECTION.
000060* DLL TEST ATTEMPT, ADD 2 NUMBERS, RETURN RESULT
000070 DATA DIVISION.
000080 LINKAGE SECTION.
000090 01  NUMBER1                  PIC S9(9) COMP-5.
000100 01  NUMBER2                  PIC S9(9) COMP-5.
000110 01  NUMBER3                  PIC S9(9) COMP-5.
000120 PROCEDURE DIVISION WITH STDCALL LINKAGE USING NUMBER1 NUMBER2 NUMBER3.
000160 0000-MAIN SECTION.
000170     ADD NUMBER1 TO NUMBER2 GIVING NUMBER3.
000180     EXIT PROGRAM.

The main program. You'll see I was able to take advantage of a few relevant Win32 API functions that are statically-linked into the executable
Code:
000010 @OPTIONS MAIN,NOALPHA
000020 IDENTIFICATION DIVISION.
000030 PROGRAM-ID. COBDLLMAIN.
000040* COMPILER. FUJITSU COBOL 3.0.
000050 ENVIRONMENT DIVISION.
000060 INPUT-OUTPUT SECTION.
000070* DLL TEST ATTEMPT, ADD 2 NUMBERS, RETURN RESULT
000080 DATA DIVISION.
000090 WORKING-STORAGE SECTION.
000100 01  DLL-CALL-DATA.
000110     04  DLL-NAME.
000120         08               PIC X(13) VALUE "COBDLLTST.DLL".
000130         08               PIC X VALUE X'00'.
000140     04  DLL-PROC-NAME.
000150         08               PIC X(09) VALUE "COBDLLTST".
000160         08               PIC X VALUE X'00'.
000170     04  DLL-HANDLE       PIC S9(9) COMP-5.
000180     04  DLL-UNLOAD       PIC S9(9) COMP-5.
000190     04  DLL-PROC-NUM     PIC S9(9) COMP-5.
000200     04  DLL-PROC-ADDR REDEFINES DLL-PROC-NUM POINTER.
000210     04  DLL-LAST-ERROR   PIC S9(9) COMP-5.
000220 01  NUMBER1              PIC S9(9) COMP-5.
000230 01  NUMBER2              PIC S9(9) COMP-5.
000240 01  NUMBER3              PIC S9(9) COMP-5.
000250 PROCEDURE DIVISION.
000260 0000-MAIN SECTION.
000270     DISPLAY "ENTER FIRST NUMBER: ".
000280     ACCEPT NUMBER1.
000290     DISPLAY "ENTER SECOND NUMBER: ".
000300     ACCEPT NUMBER2.
000310*************************************************************
000320* LOAD THE DLL
000330*************************************************************
000340     DISPLAY "LOADING TEST DLL..." DLL-NAME.
000350     CALL "LoadLibraryA" WITH STDCALL LINKAGE
000360        USING
000370           BY REFERENCE DLL-NAME
000380     END-CALL.
000390     MOVE PROGRAM-STATUS TO DLL-HANDLE.
000400     IF DLL-HANDLE = 0
000410        DISPLAY "ERROR IN LOAD : " DLL-NAME
000420        PERFORM 1000-LASTERROR
000430     END-IF.
000440*************************************************************
000450* GET TEST PROCEDURE ADDRESS
000460*************************************************************
000470     DISPLAY "GETTING TEST PROCEDURE..." DLL-PROC-NAME
000480     CALL "GetProcAddress" WITH STDCALL LINKAGE
000490        USING
000500           BY VALUE DLL-HANDLE
000510           BY REFERENCE DLL-PROC-NAME
000520     END-CALL.
000530     MOVE PROGRAM-STATUS TO DLL-PROC-NUM.
000540     IF DLL-PROC-ADDR = NULL
000550        DISPLAY "ERROR IN PROC LOAD : " DLL-PROC-NAME
000560        PERFORM 1000-LASTERROR
000570     END-IF.
000580*************************************************************
000590* NOW USE THE DLL PROCEDURE
000600*************************************************************
000610****!FOR DLL CALL TO WORK, WE MUST BE ABLE TO CALL A PROCEDURE
000620****!AS LISTED BELOW THIS COMMENT.
000630*    CALL DLL-PROC-ADDR WITH STDCALL LINKAGE
000640*          USING
000650*          BY REFERENCE NUMBER1
000660*          BY REFERENCE NUMBER2
000670*          BY REFERENCE NUMBER3
000680*    END-CALL.
000690     DISPLAY "NUMBER3 = " NUMBER3.
000700*************************************************************
000710* FREE THE DLL
000720*************************************************************
000730     DISPLAY "FREEING TEST DLL..." DLL-NAME.
000740     CALL "FreeLibrary" WITH STDCALL LINKAGE
000750        USING
000760           BY VALUE DLL-HANDLE
000770     END-CALL.
000780     MOVE PROGRAM-STATUS TO DLL-UNLOAD.
000790     IF DLL-UNLOAD = 0
000800       DISPLAY "ERROR IN DLL UNLOAD : " DLL-NAME
000810       PERFORM 1000-LASTERROR
000820     END-IF.
000830*************************************************************
000840     GOBACK.
000850
000860 1000-LASTERROR SECTION.
000870     CALL "GetLastError" WITH STDCALL LINKAGE
000880     END-CALL.
000890     MOVE PROGRAM-STATUS TO DLL-LAST-ERROR.
000900     DISPLAY "EXTENDED ERROR CODE = " DLL-LAST-ERROR.
000910     GOBACK.
 
Okay here we go...you can't do dynamic association like I was trying, but you can do static DLL association (not the same as static or dynamic linking...are we confused yet? ;) )

How you do it: The static association is established through the Fujitsu COBOL runtime, which means we need to configure it. For the directory you run the program in, you need a COBOL85.CBR file.

To configure it, you define an entry section, and then define DLLName = procedure name. Example follows:

Code:
[COBDLL2]
@IconName=COB85EXE
@ScrnSize=(80,24)
@CnslWinSize=(80,24)
@CnslBufLine=100
@WinCloseMsg=ON
@EnvSetWindow=USE
@AllFileExclusive=NO
@CBR_PrintTextPosition=TYPE1
@CBR_TextAlign=BOTTOM
[COBDLL2.ENTRY]
COBDLLTST=COBDLLTST.DLL

Then for the main code, dynamic linking is required as well as literal alphabetic interpretation. The procedure name becomes a valid entry point and therefore a valid call (the runtime loads the DLL upon startup). Example follows:

Code:
000010 @OPTIONS MAIN,DLOAD,NOALPHAL
000020 IDENTIFICATION DIVISION.
000030 PROGRAM-ID. COBDLL2.
000040* COMPILER. FUJITSU COBOL 3.0.
000050 ENVIRONMENT DIVISION.
000060 INPUT-OUTPUT SECTION.
000070* DLL TEST ATTEMPT, ADD 2 NUMBERS, RETURN RESULT
000080 DATA DIVISION.
000090 WORKING-STORAGE SECTION.
000100 01  NUMBER1              PIC S9(9) COMP-5.
000110 01  NUMBER2              PIC S9(9) COMP-5.
000120 01  NUMBER3              PIC S9(9) COMP-5.
000130 PROCEDURE DIVISION.
000140 0000-MAIN SECTION.
000150     DISPLAY "ENTER FIRST NUMBER: ".
000160     ACCEPT NUMBER1.
000170     DISPLAY "ENTER SECOND NUMBER: ".
000180     ACCEPT NUMBER2.
000190     CALL "COBDLLTST" USING NUMBER1, NUMBER2, NUMBER3.
000200     DISPLAY "NUMBER3 = " NUMBER3.
000210     STOP RUN.

It's not quite still what I was looking for. Problem: heavily run-time dependent and dependent on that CBR file showing up. That file becomes as much the program as the EXE itself.
 
why not use COM ?

Isn't that only applicable to things written as COM objects? Besides, I've found (the hard way) there's no guarantee COM is even available on all Windows systems.
 
Why not try

000010 @OPTIONS MAIN,DLOAD,NOALPHAL
000020 IDENTIFICATION DIVISION.
000030 PROGRAM-ID. COBDLL2.
000040* COMPILER. FUJITSU COBOL 3.0.
000050 ENVIRONMENT DIVISION.
000060 INPUT-OUTPUT SECTION.
000070* DLL TEST ATTEMPT, ADD 2 NUMBERS, RETURN RESULT
000080 DATA DIVISION.
000090 WORKING-STORAGE SECTION.
000095 01 WS-CALL-COBDLLTST PIC X(9) VALUE "COBDLLTST".
000097 01 DISPLAY-NBR PIC -Z(9).
000100 01 NUMBER1 PIC S9(9) COMP-5.
000110 01 NUMBER2 PIC S9(9) COMP-5.
000120 01 NUMBER3 PIC S9(9) COMP-5.
000130 PROCEDURE DIVISION.
000140 0000-MAIN SECTION.
000150 DISPLAY "ENTER FIRST NUMBER: ".
000160 ACCEPT NUMBER1.
000170 DISPLAY "ENTER SECOND NUMBER: ".
000180 ACCEPT NUMBER2.
000190 CALL WS-CALL-COBDLLTST USING
000200 NUMBER1, NUMBER2, NUMBER3
000210 ON EXCEPTION
000220 DISPLAY "BAD CALL TO COBDLLTST"
000230 NOT ON EXCEPTION
000240 CANCEL WS-CALL-COBDLLTST
000250 END-CALL.
000255 MOVE NUMBER3 TO DISPLAY-NBR
000260 DISPLAY "NUMBER 3 = " DISPLAY-NBR.
000270 STOP RUN.

Then the cobol85.cbr entries would not be needed unless you are doing some other file associations.

bawstl
 
Why not try ... then the cobol85.cbr entries would not be needed unless you are doing some other file associations.

Because it doesn't work on a DLL with a separate name or multiple calls present. While it worked on the program that was presented in this thread, when I tried it with the working program which I wanted to place multiple DLL calls in...

Code:
JMP0015I-U CANNOT CALL PROGRAM 'open_file'. CODE=0x7E PGM=WORDCNT3C ADR=004016B2
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top