gnucobol-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[open-cobol-list] Parameter passing to C-functions


From: Martin Ancher Holm
Subject: [open-cobol-list] Parameter passing to C-functions
Date: Thu, 5 Jun 2008 21:53:57 +0200

Hi!

I'm having a problem calling C-functions from OpenCobol.

If I make my own C-function then everything works, but when a C- function with the same signature is in a linked systemlibrary, the pointers returned are corrupt.

/* ccalltest.h */
#include <stdio.h>
#include <stdlib.h>

typedef struct { int x; } CFAllocatorRef;
typedef struct { int x; } CFStringRef;

CFAllocatorRef CFAllocatorGetDefault(void);
CFStringRef CFStringCreateWithCString(
        CFAllocatorRef alloc,
        const char *cStr,
        int encoding);

/* ccalltest.c */
#include "ccalltest.h"

CFAllocatorRef CFAllocatorGetDefault(void) {
        CFAllocatorRef *cfa;
        cfa = malloc(sizeof(CFAllocatorRef));
        
        printf("CFAllocatorGetDefault/\n");
        cfa->x = 6;
        return *cfa;
}

CFStringRef CFStringCreateWithCString(
        CFAllocatorRef alloc,
        const char *cStr,
        int encoding) {

        CFStringRef *cfs;
        cfs = malloc(sizeof(CFStringRef));
        cfs->x = 2;

        printf("CFStringCreateWithCString/\n");
        printf("cfs.x/%d/\n", cfs->x);
        printf("cstr/%s/\n", cStr);
        printf("encoding/%d/\n", encoding);
        printf("allocator/x/%d/\n", alloc.x);
        return *cfs;
}

      * tstccall.cbl

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TSTCCALL.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 CARBON.       
          03 COREF-ALLOCATOR            USAGE POINTER.

          03 CONST-1                    PIC  9(09) BINARY.
          03 NIB-MAIN.
             05 NIB-MAIN-VALUE          PIC  X(04) VALUE 'main'.
             05 NIB-MAIN-NULL           PIC  9(01) BINARY VALUE ZERO.
          03 NIB-MAIN-CFS               USAGE POINTER.

       PROCEDURE DIVISION.

       000-MAIN SECTION.
          CALL 'CFAllocatorGetDefault'
               RETURNING COREF-ALLOCATOR
          DISPLAY 'COREF-ALLOCATOR/' COREF-ALLOCATOR

          MOVE  1 TO CONST-1

          CALL 'CFStringCreateWithCString' USING
               BY VALUE     COREF-ALLOCATOR
               BY REFERENCE NIB-MAIN
               BY VALUE     CODEPAGE-MAC-ROMAN
               GIVING       NIB-MAIN-CFS
          DISPLAY 'NIB-MAIN-CFS/' NIB-MAIN-CFS

          GOBACK
       .

Compiling by:
$ cobc -x tstccall.cbl ccalltest.c -fstatic-call
/var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27094_0.c: In function ‘TSTCCALL_’: /var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27094_0.c:115: warning: assignment makes pointer from integer without a cast /var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27094_0.c:138: warning: assignment makes pointer from integer without a cast

Program running:
$ ./tstccall
CFAllocatorGetDefault/
COREF-ALLOCATOR/0000000006
CFStringCreateWithCString/
cfs.x/2/
cstr/main/
encoding/1/
allocator/x/6/
NIB-MAIN-CFS/0000000002

Everything works fine. A struct created in CFAllocatorGetDefault with the int x is passed on to CFStringCreateWithCString, and the the data is intact, and I can print the int x.

Ok now it's time to go for the real deal. I'm gonna get rid of my testfile ccalltest.c, and link to a library, that has the exact same signature.

( I've made a symbolic link to the library, since the linker expects a library to be prefixed with 'lib' and postfixed with '.dylib'.
$ ls -l libCoreFoundation.dylib
lrwxr-xr-x 1 ancher ancher 66 5 Jun 19:46 libCoreFoundation.dylib - > /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation )

Compiling by:
$ cobc -x tstccall.cbl -lCoreFoundation -L. -fstatic-call
/var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27134_0.c: In function ‘TSTCCALL_’: /var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27134_0.c:115: warning: assignment makes pointer from integer without a cast /var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27134_0.c:138: warning: assignment makes pointer from integer without a cast

Program running:
$ ./tstccall
COREF-ALLOCATOR/2689348000
Bus error

This failes, as it seem the pointer variable size is too small for the pointer returned, therefor the program crashes when a wrong pointer is sent to CFStringCreateWithCString.

I've tried to fix the problem by changing the variable COREF-ALLOCATOR USAGE POINTER to COREF-ALLOCATOR PIC 9(19) BINARY.

Compiling by:
$ cobc -x tstccall.cbl ccalltest.c -fstatic-call
/var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27235_0.c: In function ‘TSTCCALL_’: /var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27235_0.c:139: warning: assignment makes pointer from integer without a cast

Program running:
$ ./tstccall
CFAllocatorGetDefault/
COREF-ALLOCATOR/000000000000000006
CFStringCreateWithCString/
cfs.x/2/
cstr/(null)/
encoding/8668/
allocator/x/6/
NIB-MAIN-CFS/0000000002

Compiling by:
$ cobc -x tstccall.cbl -lCoreFoundation -L. -fstatic-call
/var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27256_0.c: In function ‘TSTCCALL_’: /var/folders/kt/ktBjHdTB2RaYWU+1Yxvqm++++TI/-Tmp-//cob27256_0.c:139: warning: assignment makes pointer from integer without a cast

Program running:
$ ./tstccall
COREF-ALLOCATOR/000000001605619296
Bus error

This did not solve the problem, and now even my own testdriver failes as well.

One interesting thing though is that the pointer returned is 10 digits, and thus too small for the 9 digits reserved for the USAGE POINTER in OpenCobol.

To me it seems the that the C-api in OpenCobol works as long as the operating system does NOT return pointers larger than 9 digits.

Yours faithfully
Martin Ancher Holm

reply via email to

[Prev in Thread] Current Thread [Next in Thread]