From: jlcaverlyca@yahoo.ca on
Hi,
I'm using MicroFocus Visual Object Cobol Product Version 1.0.27 and
Visual Basic 5.0 SP3.

After doing some Googling, I've created my first Cobol DLL, which I
have compiled, and have called from VB5.

The Cobol DLL code is as follows;

IDENTIFICATION DIVISION.
PROGRAM-ID. COBDLL.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
CALL-CONVENTION 3 IS WINAPI.
DATA DIVISION.
WORKING-STORAGE SECTION.
LINKAGE SECTION.
*
* Short (Integer) S9(4) Comp-5
* Long (Long) S9(8) Comp-5
*
01 VB-SHORT PIC S9(4) COMP-5.
01 VB-LONG PIC S9(8) COMP-5.
01 VB-CHAR PIC X(5).

PROCEDURE DIVISION WINAPI.
PROC-1.

ENTRY "testcall" USING BY VALUE VB-SHORT
BY VALUE VB-LONG
BY REFERENCE VB-CHAR.

IF VB-SHORT > VB-LONG
MOVE "A > B" TO VB-CHAR
MOVE ZERO TO RETURN-CODE
ELSE
MOVE "B > A" TO VB-CHAR
MOVE 1 TO RETURN-CODE
END-IF

EXIT PROGRAM.

My VB5 code is as follows;

Module1.bas:
Declare Sub TESTCALL Lib "cobdll.dll" _
(VBShort As Integer, VBLong As Long, ByVal VBChar As String)

Form1.bas:
Private Sub Form_Load()
Dim thestring As String * 5
Dim num1 As Integer
Dim num2 As Long
num1 = 1
num2 = 2
TESTCALL num1, num2, thestring
MsgBox thestring
End
End Sub

A couple of questions.
First, I have to Declare the Sub as TESTCALL, as the DLL compiles this
as UpperCase. I found this out by doing a DUMPBIN on the DLL. How do I
make the DLL compile the Sub as testcall or TestCall?

Second, as I step through the code in VB5 after TESTCALL, num1 becomes
8258, num2 is 2, and thestring is still five spaces.

When I make num1 = 2 and num2 = 1, after TESTCALL num1 becomes 8258,
num2 is 1, and thestring is still five spaces.

I have a feeling that my problem may be in the CALL-CONVENTION, but I'm
not sure what to change it to.

Thanks in advance to anyone who knows what the problem is.

Joe

From: epc8 on
jlcaverlyca(a)yahoo.ca wrote:

> Hi,
> I'm using MicroFocus Visual Object Cobol Product Version 1.0.27 and
> Visual Basic 5.0 SP3.
>
> After doing some Googling, I've created my first Cobol DLL, which I
> have compiled, and have called from VB5.
>
> My VB5 code is as follows;
>
> Module1.bas:
> Declare Sub TESTCALL Lib "cobdll.dll" _
> (VBShort As Integer, VBLong As Long, ByVal VBChar As String)
>

> A couple of questions.
> First, I have to Declare the Sub as TESTCALL, as the DLL compiles this
> as UpperCase. I found this out by doing a DUMPBIN on the DLL. How do I
> make the DLL compile the Sub as testcall or TestCall?

1. Does the "case" directive you included in a recent post have any
effect on the symbols your program *exports*?

2. add an ALIAS "TESTCALL" to your declare, then you can call your Sub
whatever you want.

3. add a .def file to your build (somehow) which contains

EXPORTS
myname=TESTCALL


>
> Second, as I step through the code in VB5 after TESTCALL, num1 becomes
> 8258, num2 is 2, and thestring is still five spaces.
>
> When I make num1 = 2 and num2 = 1, after TESTCALL num1 becomes 8258,
> num2 is 1, and thestring is still five spaces.
>
> I have a feeling that my problem may be in the CALL-CONVENTION, but I'm
> not sure what to change it to.
>

Usually if your calling convention is off, you get a run time error
from VB. The calling convention must be stdcall for which WINAPI is an
older synonym. Passing the string from Basic ByVal looks right.

See http://supportline.microfocus.com/examplesandutilities/nesamp.asp

for some examples from NetExpress.

From: epc8 on
jlcaverlyca(a)yahoo.ca wrote:
> Hi,
> I'm using MicroFocus Visual Object Cobol Product Version 1.0.27 and
> Visual Basic 5.0 SP3.
>
> After doing some Googling, I've created my first Cobol DLL, which I
> have compiled, and have called from VB5.
>
> The Cobol DLL code is as follows;
>
> IDENTIFICATION DIVISION.
> PROGRAM-ID. COBDLL.
> ENVIRONMENT DIVISION.
> CONFIGURATION SECTION.
> SPECIAL-NAMES.
> CALL-CONVENTION 3 IS WINAPI.
> DATA DIVISION.
> WORKING-STORAGE SECTION.
> LINKAGE SECTION.
> *
> * Short (Integer) S9(4) Comp-5
> * Long (Long) S9(8) Comp-5
> *
> 01 VB-SHORT PIC S9(4) COMP-5.
> 01 VB-LONG PIC S9(8) COMP-5.
> 01 VB-CHAR PIC X(5).
>
> PROCEDURE DIVISION WINAPI.
> PROC-1.
>
> ENTRY "testcall" USING BY VALUE VB-SHORT
> BY VALUE VB-LONG
> BY REFERENCE VB-CHAR.
>
> IF VB-SHORT > VB-LONG
> MOVE "A > B" TO VB-CHAR
> MOVE ZERO TO RETURN-CODE
> ELSE
> MOVE "B > A" TO VB-CHAR
> MOVE 1 TO RETURN-CODE
> END-IF
>
> EXIT PROGRAM.
>
> My VB5 code is as follows;
>
> Module1.bas:
> Declare Sub TESTCALL Lib "cobdll.dll" _
> (VBShort As Integer, VBLong As Long, ByVal VBChar As String)
>
> Form1.bas:
> Private Sub Form_Load()
> Dim thestring As String * 5
> Dim num1 As Integer
> Dim num2 As Long
> num1 = 1
> num2 = 2
> TESTCALL num1, num2, thestring
> MsgBox thestring
> End
> End Sub
>

See my other message. This time I'm looking at your COBOL program in
more depth. VB passes arguments by reference unless you specify ByVal.
However, you do want to pass the string ByVal, otherwise you would pass
a pointer to a string descriptor instead of a pointer to the string.

On the COBOL side, I think changing your BY VALUE to BY REFERENCE for
the two integers might help.

Lastly, I'm not certain that your two COMP-5 items are really different
sizes. They might be. But if you really were passing them by value
before and your program did not crash, then I suspect that you were
really passing 3 4-byte arguments. VB is calling a subroutine in the
dll as if it takes 3 pointers.

[Sorry, I have not written any VB callable DLLs in COBOL, but I have
done so in a variety of other languages.]

From: jlcaverlyca@yahoo.ca on
epc8(a)juno.com wrote:
> See my other message. This time I'm looking at your COBOL program in
> more depth. VB passes arguments by reference unless you specify ByVal.
> However, you do want to pass the string ByVal, otherwise you would pass
> a pointer to a string descriptor instead of a pointer to the string.
>
> On the COBOL side, I think changing your BY VALUE to BY REFERENCE for
> the two integers might help.
>
> Lastly, I'm not certain that your two COMP-5 items are really different
> sizes. They might be. But if you really were passing them by value
> before and your program did not crash, then I suspect that you were
> really passing 3 4-byte arguments. VB is calling a subroutine in the
> dll as if it takes 3 pointers.
>
> [Sorry, I have not written any VB callable DLLs in COBOL, but I have
> done so in a variety of other languages.]

I have changed my VB Declare to pass the numerics as ByVal. I have also
been looking at some of the other code on the net that has
"CALL-CONVENTION .. IS WINAPI. I noticed that alot of these were 74,
instead of the 3 that I was using. So, I changed it to 74.

I re-compiled the DLL, and it now works as it should. I changed the
values of num1 and num2 to make sure that "A > B" and "B > A" are
correctly displayed from VB.

I looked up in the VisOC help, and found "Call Conventions for
Interfacing with Mixed Languages", which breaks down how a call
convention number is determined. Here's how I interpret it;

1001010 - 74
||||||| Process parameters from right-to-left
||||||- Parameters removed from stack by called program
|||||-- RETURN-CODE is updated on exit
||||--- Call is resolved at link time
|||---- Reserved (always 0)
||----- Reserved (always 0)
|------ The call conforms to the Windows stdcall calling convention

0000011 - 3
||||||| Process parameters from left-to-right
||||||- Parameters removed from stack by called program
|||||-- RETURN-CODE is updated on exit
||||--- Normal linking behavior
|||---- Reserved (always 0)
||----- Reserved (always 0)
|------ The call does not conform to the Windows stdcall calling
convention

I think that making the call conform to the Windows stdcall calling
convention may have had something to do with it.

Many thanks for your assistance.

Joe

From: epc8 on

jlcaverlyca(a)yahoo.ca wrote:
>
> I have changed my VB Declare to pass the numerics as ByVal. I have also
> been looking at some of the other code on the net that has
> "CALL-CONVENTION .. IS WINAPI. I noticed that alot of these were 74,
> instead of the 3 that I was using. So, I changed it to 74.
>
> I re-compiled the DLL, and it now works as it should. I changed the
> values of num1 and num2 to make sure that "A > B" and "B > A" are
> correctly displayed from VB.
>
> I looked up in the VisOC help, and found "Call Conventions for
> Interfacing with Mixed Languages", which breaks down how a call
> convention number is determined. Here's how I interpret it;
>
> 1001010 - 74
> ||||||| Process parameters from right-to-left
> ||||||- Parameters removed from stack by called program
> |||||-- RETURN-CODE is updated on exit
> ||||--- Call is resolved at link time
> |||---- Reserved (always 0)
> ||----- Reserved (always 0)
> |------ The call conforms to the Windows stdcall calling convention
>
> 0000011 - 3
> ||||||| Process parameters from left-to-right
> ||||||- Parameters removed from stack by called program
> |||||-- RETURN-CODE is updated on exit
> ||||--- Normal linking behavior
> |||---- Reserved (always 0)
> ||----- Reserved (always 0)
> |------ The call does not conform to the Windows stdcall calling
> convention
>
> I think that making the call conform to the Windows stdcall calling
> convention may have had something to do with it.
>
> Many thanks for your assistance.
>
> Joe

Confusion arose here because WINAPI has been used as a synonym for two
different things, convention 3 in 16 bit Windows (FAR PASCAL) and
convention 74 in 32 bit Windows (stdcall). Sorry I missed it earlier
:-(.

We can blame the C programmers for this one! Yes, with the right set of
header files, I can define a C function as being FAR PASCAL and it will
still compile and run on Windows XP.