Microsoft KB Archive/71274

From BetaArchive Wiki

Microsoft Knowledge Base

How to Pass Parameters Between Basic and C (Part 2 of 2)

Last reviewed: January 12, 1995
Article ID: Q71274

The information in this article applies to:

  • Microsoft Basic Professional Development System (PDS) for MS-DOS, versions 7.0 and 7.1
  • Microsoft Basic Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2
  • Microsoft QuickBasic for MS-DOS, versions 4.0, 4.0b, and 4.5
  • Standard and Professional Editions of Microsoft Visual Basic for MS-DOS, version 1.0
  • Microsoft C Optimizing Compiler versions 5.00, 5.10, and 6.00 for MS-DOS and MS OS/2
  • Microsoft QuickC versions 1.00, 1.01, 2.00, 2.01, and 2.50 for MS-DOS

SUMMARY

This article contains Part 2 of 2 of the complete text of "How to Pass Parameters between Basic and C." To obtain Part 1 of 2, please see the following article in the Microsoft Knowledge Base:

ARTICLE-ID: Q50062

TITLE     : How to Pass Parameters Between Basic and C (Part 1 of 2)

MORE INFORMATION

This is part 2 of 2:

COMPILING AND LINKING THE SAMPLE PROGRAMS

Following the appendix is a series of examples that demonstrate the interlanguage calling capabilities between Basic and C.

When compiling the sample Basic programs, you can compile with or without the /O (BCOM stand-alone library) option. The following uses the BCOM library to produce a stand-alone Basic program:

   BC /O Basicprogramname;

The following uses the BRUN library, so that the compiled program needs the BRUN run-time library on disk when it is executed:

   BC Basicprogramname

When compiling the sample C programs, one of the following compile lines should be used:

   Compile Line               Used For
   ------------               --------

   CL /c /AM Cprogramname;    C 5.00 and C 5.10

   QCL /c /AM Cprogramname;   QuickC

NOTE: For convenience, the medium memory model is used for the C programs. If the large memory model were used instead (/AL instead of /AM), all pointers would have to be explicitly defined as near.

To link the programs, use the following link line:

   LINK /NOE Basicprogramname Cprogramname;

APPENDIX: COMMON PITFALLS

The following common pitfalls are all explained in more detail in the main text. Use this appendix as a checklist when you encounter problems while doing mixed-language programming.

  1. Make certain the version numbers of the two languages are compatible.

    The following table specifies which versions of Microsoft Basic can be linked with specific versions of Microsoft C or QuickC:

                        Basic
          QuickBasic    Compiler  <->    C       QuickC
          ----------    --------  ---    -       ------
    
          4.00            --      <->    5.00    1.00
            --          6.00      <->    5.10    1.01
          4.00b    or   6.00b     <->    5.10    1.01
          4.50     or   7.00      <->    5.10    2.00 or 2.01
            --          7.10      <->    6.00    2.50
    
  2. Make certain that a C routine is declared with CDECL in Basic or that in C the pascal directive is used when defining the procedure. This ensures the same calling convention is being used.
  3. Make sure that the graphic libraries are not included in the C libraries. If the graphic libraries are included, duplicate definition errors will occur.
  4. Use the /NOE switch when linking to avoid duplicate definition errors. If duplicate definition errors still occur, also use the /NOD switch when linking.
  5. Watch for incompatible C functions such as system() and getenv().
  6. When passing strings to C, check for two things:

    a. If a C function will use the string, it should be NULL (CHR$(0))

          terminated.

    b. SADD should be used instead of VARPTR to pass the actual address

          of the string. VARPTR returns the offset to the string
          descriptor, not to the string itself.
  7. The C routine should be compiled in the medium or large memory model. If the large memory model is used, then all pointers to Basic variables must be explicitly defined as near.
  8. When using VARSEG, VARPTR, or SADD to pass addresses to C, it is important to check the function definition. Since Basic normally passes all parameters by reference, any parameter that is an address should be declared using BYVAL. If BYVAL is not used, then Basic creates a temporary variable to hold the address and then passes a pointer to this variable (in effect, Basic passes a pointer to a pointer).
  9. If you enter the libraries on the link line, then the Basic libraries must precede all others.

PASSING NUMERIC VARIABLES FROM Basic TO C BY NEAR REFERENCE

Basic Program

DECLARE SUB NumericNear CDECL (a%,b&,c!,d#)

a% = 32767 b& = 32769 c! = 123.312 d# = 129381.333#

CLS CALL NumericNear(a%, b&, c!, d#) END

C Routine

#include <stdio.h>

void NumericNear(int *a, long *b, float *c, double *d) {
   printf("INTEGER %d\n", *a);
   printf("LONG    %ld\n", *b);
   printf("FLOAT   %f\n", *c);
   printf("DOUBLE  %lf\n", *d);

}

Output

INTEGER 32767

LONG     32769
FLOAT    123.311996
DOUBLE   129381.333000

PASSING NUMERIC VARIABLES BETWEEN Basic AND C BY FAR REFERENCE

Basic Program

DECLARE SUB NumericFar CDECL (_

        BYVAL p1o AS INTEGER, BYVAL p1s AS INTEGER,_
        BYVAL p2o AS INTEGER, BYVAL p2s AS INTEGER,_
        BYVAL p3o AS INTEGER, BYVAL p3s AS INTEGER,_
        BYVAL p4o AS INTEGER, BYVAL p4s AS INTEGER)

a% = 32767 b& = 32769 c! = 123.312 d# = 129381.333#

CLS CALL NumericFar(VARPTR(a%), VARSEG(a%),_

                VARPTR(b&), VARSEG(b&),_
                VARPTR(c!), VARSEG(c!),_
                VARPTR(d#), VARSEG(d#))
END

C Routine

#include <stdio.h>
void NumericFar(int far *a, long far *b, float far *c, double far *d)

{

   printf("INTEGER  %d\n", *a);
   printf("LONG     %ld\n", *b);
   printf("FLOAT    %f\n", *c);
   printf("DOUBLE   %lf\n", *d);
}

Output

INTEGER 32767

LONG     32769
FLOAT    123.311996
DOUBLE   129381.333000

PASSING NUMERIC VARIABLES FROM Basic TO C BY VALUE

Basic Program

DECLARE SUB NumericValue CDECL (_

            BYVAL p1 AS INTEGER,_
            BYVAL p2 AS LONG,_
            BYVAL p3 AS SINGLE,_
            BYVAL p4 AS DOUBLE)

a% = 32767 b& = 32769 c! = 123.312 d# = 129381.333#

CLS CALL NumericValue(a%, b&, c!, d#) END

C Routine

#include <stdio.h>

struct struct_int {

   int x;

};

struct struct_long {

   long x;

};

struct struct_float {

   float x;

};

struct struct_double {

   double x;

};

void NumericValue(struct struct_int a, struct struct_long b,
                  struct struct_float c, struct struct_double d) {
   printf("INTEGER  %d\n", a.x);
   printf("LONG     %ld\n", b.x);
   printf("FLOAT    %f\n", c.x);
   printf("DOUBLE   %lf\n", d.x);
}

Output

INTEGER 32767

LONG     32769
FLOAT    123.311996
DOUBLE   129381.333000

PASSING A C CHAR TO Basic

Basic Program

DECLARE SUB CSUB CDECL()

TYPE chartype

   character AS STRING *1

END TYPE

CALL CSUB

END

SUB BASSUB(cchar AS chartype)

   PRINT cchar.character
   PRINT LEN(cchar.character)

END SUB

C Routine

#include <stdio.h>

struct character {

   char thechar;

};

extern void pascal bassub(struct character *baschar);

struct character *c_char;

void csub() {
   c_char->thechar = 'A';
   bassub(c_char);

}

Output

A

 1

PASSING A Basic VARIABLE-LENGTH STRING TO C BY NEAR REFERENCE

Basic Program

DECLARE SUB StringNear CDECL (_

        BYVAL p1o AS INTEGER,_
        p3 AS INTEGER)

CLS

a$ = "This is a test" + CHR$(0) CALL StringNear(SADD(a$), LEN(a$)) END

C Routine

#include <stdio.h>

void StringNear(char *a, int *len) {
   int i;
   printf("The string is : %s \n\n",a);
   printf(" Index       Value       Character\n");

   for (i=0;i < *len; i++) {
      printf("  %2d          %3d            %c\n",i,a[i],a[i]);
   };

}

Output

The string is : This is a test

 Index       Value       Character
   0           84            T
   1          104            h
   2          105            i
   3          115            s
   4           32
   5          105            i
   6          115            s
   7           32
   8           97            a
   9           32
  10          116            t
  11          101            e
  12          115            s
  13          116            t
  14            0

PASSING A Basic VARIABLE-LENGTH STRING TO C BY FAR REFERENCE

Basic Program

DECLARE SUB StringFar CDECL (_

        BYVAL p1o AS INTEGER,_
        BYVAL p1s AS INTEGER,_
        p3 AS INTEGER)

CLS

a$ = "This is a test" + CHR$(0) CALL StringFar(SADD(a$), VARSEG(a$), LEN(a$)) END

C Routine

#include <stdio.h>

void StringFar(char far *a, int *len) {
   int i;
   printf("The string is : %s \n\n",a);
   printf(" Index       Value       Character\n");

   for (i=0;i < *len; i++) {
      printf("  %2d          %3d            %c\n", i, a[i], a[i]);
   };

}

Output

The string is : This is a test

 Index       Value       Character
   0           84            T
   1          104            h
   2          105            i
   3          115            s
   4           32
   5          105            i
   6          115            s
   7           32
   8           97            a
   9           32
  10          116            t
  11          101            e
  12          115            s
  13          116            t
  14            0

PASSING A Basic STRING DESCRIPTOR TO C

Basic Program

DECLARE SUB StringNear CDECL (a$)

CLS array$ = "This is a test" + CHR$(0) CALL StringNear(array$) END

C Routine

#include <stdio.h>

struct struct_string {

   int length;
   char *address;

};

void StringNear(struct struct_string *string) {
   int i;
   printf("The string is : %s\n\n",string->address);
   printf(" Index       Value       Character\n");

   for (i=0;i < string->length; i++) {
      printf("  %2d          %3d            %c\n", i,
             string->address[i], string->address[i]);
   };

}

Output

The string is : This is a test

 Index       Value       Character
   0           84            T
   1          104            h
   2          105            i
   3          115            s
   4           32
   5          105            i
   6          115            s
   7           32
   8           97            a
   9           32
  10          116            t
  11          101            e
  12          115            s
  13          116            t
  14            0

PASSING A Basic FIXED-LENGTH STRING TO C BY NEAR REFERENCE

Basic Program

DECLARE SUB StringNear CDECL (_

            BYVAL p1o AS INTEGER,_
            p3 AS INTEGER)

DIM a AS STRING * 15

CLS a = "This is a test" + CHR$(0) CALL StringNear(VARPTR(a), LEN(a)) END

C Routine

#include <stdio.h>

void StringNear(char *a, int *len) {
   int i;
   printf("The string is : %s \n\n",a);
   printf(" Index       Value       Character\n");

   for (i=0;i < *len; i++) {
      printf("  %2d          %3d            %c\n", i, a[i], a[i]);
   };

}

Output

The string is : This is a test

 Index       Value       Character
   0           84            T
   1          104            h
   2          105            i
   3          115            s
   4           32
   5          105            i
   6          115            s
   7           32
   8           97            a
   9           32
  10          116            t
  11          101            e
  12          115            s
  13          116            t
  14            0

PASSING A Basic FIXED-LENGTH STRING TO C BY FAR REFERENCE

Basic Program

DECLARE SUB StringFar CDECL (_

            BYVAL p1o AS INTEGER,_
            BYVAL p1s AS INTEGER,_
            p3 AS INTEGER)

DIM a AS STRING * 15

CLS a = "This is a test" + CHR$(0) CALL StringFar(VARPTR(a), VARSEG(a), LEN(a)) END

C Routine

#include <stdio.h>

void StringFar(char far *a, int *len) {
   int i;
   printf("The string is : %s \n\n", array);
   printf(" Index       Value       Character\n");

   for (i=0;i < *len; i++) {
      printf("  %2d          %3d            %c\n", i, a[i], a[i]);
   };

}

Output

The string is : This is a test

 Index       Value       Character
   0           84            T
   1          104            h
   2          105            i
   3          115            s
   4           32
   5          105            i
   6          115            s
   7           32
   8           97            a
   9           32
  10          116            t
  11          101            e
  12          115            s
  13          116            t
  14            0

PASSING A STRING FROM C TO Basic

Basic Program

DECLARE SUB CSUB CDECL()

TYPE fixstringtype

   B AS STRING * 26

END TYPE

CALL CSUB

END

SUB BASSUB(A$, B AS fixstringtype)

   PRINT A$
   PRINT LEN(A$)
   PRINT B.B
   PRINT LEN(B.B)

END SUB

C Routine

#include <string.h>

struct stringdesc {

   int length;
   char *string;

};

extern void pascal bassub(struct stringdesc *basstring,

                          char *basfixstring);

struct stringdesc *std;

char thesecondstring[26];

void csub() {
   std->length = 18;
   strcpy(std->string, "This is the string");
   strcpy(thesecondstring, "This is the second string");
   bassub(std, thesecondstring);

}

Output

This is the string

 18

This is the second string

 26

PASSING A Basic USER-DEFINED TYPE TO C BY NEAR REFERENCE

Basic Program

TYPE record

   a AS INTEGER
   b AS STRING * 20
   c AS SINGLE

END TYPE

DECLARE SUB TypeReference CDECL (p1 AS record)

CLS DIM element AS record element.a = 128 element.b = DATE$ + CHR$(0) element.c = 39.6 CALL TypeReference(element) END

C Routine

#include <stdio.h>

struct record {

   int a;
   char b[20];
   float c;

};

void TypeReference(struct record *element) {
   printf("Record.A = %d\n", element->a);
   printf("Record.B = %s\n", element->b);
   printf("Record.C = %f\n", element->c);

}

Output

Record.A = 128 Record.B = 02-02-1988 Record.C = 39.599998

PASSING A Basic USER-DEFINED TYPE TO C BY FAR REFERENCE

Basic Program

TYPE record

   a AS INTEGER
   b AS STRING * 20
   c AS SINGLE

END TYPE

DECLARE SUB TypeReference CDECL (BYVAL p1o AS INTEGER, _

                                 BYVAL p1s AS INTEGER)

CLS

DIM element AS record element.a = 128 element.b = DATE$ + CHR$(0) element.c = 39.6 CALL TypeReference(VARPTR(element), VARSEG(element)) END

C Routine

#include <stdio.h>

struct record {

   int a;
   char b[20];
   float c;

};

void TypeReference(struct record *element) {
   printf("Record.A = %d\n", element->a);
   printf("Record.B = %s\n", element->b);
   printf("Record.C = %f\n", element->c);

}

Output

Record.A = 128 Record.B = 02-02-1988 Record.C = 39.599998

PASSING A Basic INTEGER ARRAY TO C BY FAR REFERENCE

Basic Program

DECLARE SUB IntArray CDECL (_

            BYVAL p1 AS INTEGER,_
            BYVAL p2 AS INTEGER)

DEFINT A-Z DIM i AS INTEGER DIM array(10) AS INTEGER

CLS

FOR i = 1 TO 10

   array(i) = i

NEXT i

'Array must be a FAR pointer, so offset and segment must be passed:

CALL IntArray(VARPTR(array(0)), VARSEG(array(0))) LOCATE 15, 1

WHILE INKEY$ = "": WEND

PRINT "Back in Basic"

FOR i = 1 TO 10

   PRINT i, array(i)

NEXT i

END

C Routine

#include <stdio.h>

void IntArray (int far *array) {
   int i;

   printf("Index         Value\n");

   for (i=0; i < 11; i++) {
      printf("  %d          %d\n", i, array[i]);
      array[i] = array[i] + 100;
   };

}

Output

Index      Value
 0          0
 1          1
 2          2
 3          3
 4          4
 5          5
 6          6
 7          7
 8          8
 9          9
 10         10

Back in Basic

 1             101
 2             102
 3             103
 4             104
 5             105
 6             106
 7             107
 8             108
 9             109
 10            110

PASSING A Basic ARRAY OF LONG INTEGERS TO C BY FAR REFERENCE

Basic Program

DECLARE SUB LongArray CDECL (_

            BYVAL p1 AS INTEGER,_
            BYVAL p2 AS INTEGER)

DEFINT A-Z DIM i AS LONG DIM array(10) AS LONG

CLS

FOR i = 1 TO 10

   array(i) = i + 100

NEXT i

'Array must be a FAR pointer, so offset and segment must be passed:

CALL LongArray(VARPTR(array(0)), VARSEG(array(0))) LOCATE 15, 1 PRINT "Back in Basic"

FOR i = 1 TO 10

   PRINT i, array(i)

NEXT i

END

C Routine

#include <stdio.h>

void LongArray(long far *array) {
   int i;
   printf("Index         Value\n");

   for (i=0; i < 11; i++) {
      printf("  %d          %ld\n", i, array[i]);
      array[i] = array[i] + 100;
   };

}

Output

Index         Value
  0          0
  1          101
  2          102
  3          103
  4          104
  5          105
  6          106
  7          107
  8          108
  9          109
  10          110

Back in Basic

 1             201
 2             202
 3             203
 4             204
 5             205
 6             206
 7             207
 8             208
 9             209
 10            210

PASSING A Basic SINGLE-PRECISION ARRAY TO C BY FAR REFERENCE

Basic Program

DECLARE SUB FloatArray CDECL (_

            BYVAL p1 AS INTEGER,_
            BYVAL p2 AS INTEGER)

DEFINT A-Z DIM i AS SINGLE DIM array(10) AS SINGLE

CLS

FOR i = 1 TO 10

   array(i) = i + 100

NEXT i

'Array must be a FAR pointer, so offset and segment must be passed:

CALL FloatArray(VARPTR(array(0)), VARSEG(array(0))) LOCATE 15, 1 PRINT "Back in Basic"

FOR i = 1 TO 10

   PRINT i, array(i)

NEXT i

END

C Routine

#include <stdio.h>

void FloatArray(float far *array) {
   int i;

   printf("Index         Value\n");

   for (i=0; i < 11; i++) {
      printf("  %d          %f\n", i, array[i]);
      array[i] = array[i]+100;
   };

}

Output

Index         Value
 0          0.000000
 1          101.000000
 2          102.000000
 3          103.000000
 4          104.000000
 5          105.000000
 6          106.000000
 7          107.000000
 8          108.000000
 9          109.000000
 10          110.000000

Back in Basic

 1             201
 2             202
 3             203
 4             204
 5             205
 6             206
 7             207
 8             208
 9             209
 10            210

PASSING A Basic DOUBLE-PRECISION ARRAY TO C BY FAR REFERENCE

Basic Program

DECLARE SUB DoubleArray CDECL (_

            BYVAL p1 AS INTEGER,_
            BYVAL p2 AS INTEGER)

DEFINT A-Z DIM i AS DOUBLE DIM array(10) AS DOUBLE

CLS

FOR i = 1 TO 10

   array(i) = i + 100

NEXT i

'Array must be a FAR pointer, so offset and segment must be passed:

CALL DoubleArray(VARPTR(array(0)), VARSEG(array(0))) LOCATE 15, 1 PRINT "Back in Basic"

FOR i = 1 TO 10

   PRINT i, array(i)

NEXT i

END

C Routine

#include <stdio.h>

void DoubleArray(double far *array) {
   int i;

   printf("Index         Value\n");

   for (i=0; i < 11; i++) {
      printf("  %d          %lf\n", i, array[i]);
      array[i] = array[i] + 100;
   };

}

Output

Index         Value
 0          0.000000
 1          101.000000
 2          102.000000
 3          103.000000
 4          104.000000
 5          105.000000
 6          106.000000
 7          107.000000
 8          108.000000
 9          109.000000
 10          110.000000

Back in Basic

 1             201
 2             202
 3             203
 4             204
 5             205
 6             206
 7             207
 8             208
 9             209
 10            210

PASSING A Basic ARRAY OF VARIABLE-LENGTH STRINGS TO C

Basic Program

DECLARE SUB StringArray CDECL (_

            BYVAL p1o AS INTEGER,_
            BYVAL p2s AS INTEGER)

DIM array$(10)

CLS

FOR i = 0 TO 10

  array$(i) = STRING$(9, 65 + i) + CHR$(0)

NEXT i

CALL StringArray(VARPTR(array$(0)), VARSEG(array$(0))) END

C Routine

#include <stdio.h>

struct struct_string {   // structure that looks like a
   int length;           // string descriptor
   char *address;

};

void StringArray(struct struct_string far *string) {
   int i;

   printf(" Index  Length    String\n");

   for (i=0; i < 10; i++) {
      printf("  %2d     %3d     %s\n", i, string->length,
             string->address);
      string++;
   };

}

Output

 Index  Length    String
   0      10     AAAAAAAAA
   1      10     BBBBBBBBB
   2      10     CCCCCCCCC
   3      10     DDDDDDDDD
   4      10     EEEEEEEEE
   5      10     FFFFFFFFF
   6      10     GGGGGGGGG
   7      10     HHHHHHHHH
   8      10     IIIIIIIII
   9      10     JJJJJJJJJ

PASSING A Basic ARRAY OF FIXED-LENGTH STRINGS TO C

Basic Program

DECLARE SUB StringFar CDECL (_

        length%,_
        num%,_
        BYVAL p3o AS INTEGER,_
        BYVAL p3s AS INTEGER)

DIM array(10) AS STRING * 10

CLS length% = 10 num% = 3

FOR i = 0 TO 10

   array(i) = STRING$(9, 65 + i) + CHR$(0)

NEXT i

CALL StringFar(length%, num%, VARPTR(array(0)), VARSEG(array(0))) END

C Routine

#include <stdio.h>

void StringFar(int *len, int *num, char far *array) {
   int i;
   printf("The string length is : %d \n\n",*len);
   printf("The number of elements is : %d \n\n",*num);
   printf(" Index        String\n");
   for (i=0; i < *num; i++) {
      printf("  %2d         %s\n", i, array);
      array=array+*len;
   };

}

Output

The string length is : 10

The number of elements is : 3

 Index        String
   0         AAAAAAAAA
   1         BBBBBBBBB
   2         CCCCCCCCC

PASSING A Basic ARRAY OF USER-DEFINED TYPE TO C

Basic Program

TYPE record

   a AS INTEGER
   b AS STRING * 20
   c AS SINGLE

END TYPE

DECLARE SUB TypeArray CDECL (_

            BYVAL p1o AS INTEGER,_
            BYVAL p1s AS INTEGER)

DIM element(10) AS record

CLS

FOR I = 0 TO 10

   element(I).a = 128 + I
   element(I).b = STR$(I) + ". " + DATE$ + CHR$(0)
   element(I).c = 39.6 * I

NEXT I

CALL TypeArray(VARPTR(element(0)), VARSEG(element(0))) END

C Routine

#include <stdio.h>

struct record {

   int a;
   char b[20];
   float c;

};

void TypeArray(struct record far *element) {
   int i;

   for (i=0; i<3; i++) {
      printf("Record[%d].A = %d\n", i, element->a);
      printf("Record[%d].B = %s\n", i, element->b);
      printf("Record[%d].C = %f\n", i, element->c);
      printf("\n");
      element++;
   };

 }

Output

Record[0].A = 128 Record[0].B = 0. 02-02-1988 Record[0].C = 0.000000

Record[1].A = 129 Record[1].B = 1. 02-02-1988 Record[1].C = 39.599998

Record[2].A = 130 Record[2].B = 2. 02-02-1988 Record[2].C = 79.199997

PASSING A Basic TWO-DIMENSIONAL INTEGER ARRAY TO C BY FAR REFERENCE

Basic Program

DECLARE SUB TwoIntArray CDECL (_

            BYVAL p1o AS INTEGER,_
            BYVAL p1s AS INTEGER)

DIM x(4, 4) AS INTEGER

CLS

FOR i = 0 TO 4

   FOR j = 0 TO 4
       x(i, j) = i * j
   NEXT j

NEXT i

CALL TwoIntArray(VARPTR(x(0, 0)), VARSEG(x(0, 0))) END

C Routine

#include <stdio.h>

struct two_int_array {

   int a[5][5];

};

void TwoIntArray(struct two_int_array far *x) {
   int i,j;

   for (i = 0; i < 5; i++) {

      for (j = 0; j < 5; j++) {
         printf("  %3d   ",x->a[i][j]);
      };

     printf("\n");
   };

 }

Output

    0       0       0       0       0
    0       1       2       3       4
    0       2       4       6       8
    0       3       6       9      12
    0       4       8      12      16

PASSING A Basic TWO-DIMENSIONAL VARIABLE-LENGTH STRING ARRAY TO C

Basic Program

DECLARE SUB TwoStringArray CDECL (_

            BYVAL p1o AS INTEGER,_
            BYVAL p1s AS INTEGER)

DIM array$(4, 1)

CLS

FOR i = 0 TO 1

   FOR j = 0 TO 4
      array$(j, i) = STRING$(5, 65 + (i + j)) + CHR$(0)
   NEXT j

NEXT i

CALL TwoStringArray(VARPTR(array$(0, 0)), VARSEG(array$(0, 0))) END

C Routine

#include <stdio.h>

struct struct_string {

   int length;
   char *address;

};

struct string_array{

   struct struct_string x[2][5];

};

void TwoStringArray(struct string_array far *array) {
   int i,j;

   for (i = 0; i < 2; i++) {

      for(j = 0;j < 5; j++) {
         printf("  %s  ",array->x[i][j].address);
      };

      printf("\n");
   };

}

Output

  AAAAA    BBBBB    CCCCC    DDDDD    EEEEE
  BBBBB    CCCCC    DDDDD    EEEEE    FFFFF

PASSING A COMMON BLOCK FROM Basic TO C BY FAR REFERENCE

Basic Program

DECLARE SUB RCommon CDECL (_

            BYVAL p1o AS INTEGER,_
            BYVAL p1s AS INTEGER)

COMMON SHARED element1 AS INTEGER, element2 AS STRING * 20,_

              element3 AS SINGLE

element1 = 23 element2 = "DATE : " + DATE$ + CHR$(0) element3 = 309.03 CALL RCommon(VARPTR(element1), VARSEG(element1)) END

C Routine

#include <stdio.h>

struct common_block {   // structure that looks like the Basic
   int a;               // common block
   char b[20];
   float c;

};

void RCommon(struct common_block far *pointer) {
   printf("Element1 = %d\n", pointer->a);
   printf("Element2 = %s\n", pointer->b);
   printf("Element3 = %f\n", pointer->c);

}

Output

Element1 = 23 Element2 = DATE : 02-02-1988 Element3 = 309.029999

PASSING A FIXED-LENGTH STRING FROM C TO Basic BY FAR REFERENCE

Basic Program

DECLARE SUB StringFar CDECL (_

            BYVAL p1o AS INTEGER,_
            BYVAL p1s AS INTEGER,_
            p3 AS INTEGER)

DIM array AS STRING * 15

CLS array = "This is a test" + CHR$(0) CALL StringFar(VARPTR(array), VARSEG(array), LEN(array)) LOCATE 20,20 PRINT array END

C Routine

#include <stdio.h>

void StringFar(char far *a, int *len) {
   int i;

   printf("The string is : %s \n\n",a);
   printf(" Index       Value       Character\n");

   for (i = 0;i < *len; i++) {
      printf("  %2d       %3d      %c\n", i, a[i], a[i]);
   };

/* This loop writes over the end of the string */
   for (i = 10; i < *len; i++) {
      a[i] = 64;    // ASCII value for '@'
   };

}

Output

The string is : This is a test

Index       Value       Character
 0           84          T
 1          104          h
 2          105          i
 3          115          s
 4           32
 5          105          i
 6          115          s
 7           32
 8                       a
 9           32
10          116          t
11          101          e
12          115          s
13          116          t

                    This is a @@@@

C FUNCTIONS RETURNING NUMERICS TO Basic

Basic Program

DECLARE FUNCTION cintfunc% CDECL () DECLARE FUNCTION clongfunc& CDECL () DECLARE FUNCTION cdoublefunc# CDECL ()

PRINT "Integer: "; cintfunc

PRINT "Long   : "; clongfunc

PRINT "Double : "; cdoublefunc

C Routines

int cintfunc(void) {
   int theint = 32767;
   return(theint);

}

long clongfunc(void) {

   long thelong = 32769;
   return(thelong);

}

double cdoublefunc(void) {

   double thedouble = 129381.123;
   return(thedouble);

}

Output

Integer: 32767 Long : 32769 Double : 129381.123

Note: It is not currently possible to have a C function return a SINGLE- precision number to Basic. Microsoft is researching this problem and will post new information as it becomes available.

A Basic FUNCTION RETURNING A STRING TO C

Basic Program

DECLARE SUB CSUB CDECL () CALL CSUB END FUNCTION basvarfunc$(dummy%)

   basvarfunc$ = "This is the string"

END FUNCTION

C Routine

#include <stdio.h>

struct stringdesc {

   int length;
   char *string;

};

extern struct stringdesc * pascal basvarfunc(int *dummy);

struct stringdesc *std;

void csub() {
   int i;

   std = basvarfunc(0);
   printf("Length of string: %2d\r\n", std->length);

   for(i = 0; i < std->length; i++)
      printf("%c", std->string[i]);

   printf("\r\n");

}

Output

Length of string: 18 This is the string

A C FUNCTION RETURNING A STRING TO Basic

Basic Program

DECLARE FUNCTION CFUNC$ CDECL () a$ = CFUNC$ PRINT a$ PRINT len(a$)

C Routine

#include <string.h>

struct stringdesc {

   int length;        // length of the string
   char *string;      // near pointer to the string
};

struct stringdesc *std;

char thestring[18];      /* In the medium memory model this
                            string will be in DGROUP - which
                            is required for Basic    */

struct stringdesc *cfunc() {

   std->length = 18;      // length of the string
   strcpy(thestring, "This is the string");
   std->string = thestring;
   return(std);           // return pointer to string descriptor
}

Output

This is the string 8


Additional reference words: QuickBas BasicCom

KBCategory: kbprg
KBSubcategory:


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: January 12, 1995
©1997 Microsoft Corporation. All rights reserved. Legal Notices.