[Info-vax] Any Way to Pass Character String Arguments from C to Basic?
Arne Vajhøj
arne at vajhoej.dk
Mon Oct 21 23:02:16 EDT 2019
On 10/21/2019 11:31 AM, Craig Dedo wrote:
> Is there any way to pass character string arguments from a C program or procedure to a procedure written in Basic? For both languages I'm using the current versions of the languages:
> VSI C V7.4-002 on OpenVMS Alpha V8.4-2L2
> VSI BASIC V1.8-005 on OpenVMS V8.4-2L2
>
> I need to pass character string variables from a main program or procedure written in C to a subroutine written in Basic and get back character string data from the Basic subroutine. I had to write the subroutine in Basic because it needs to call a utility subroutine in Basic that uses arrays of varying-length character strings.
>
> Everything compiles and links correctly; no errors or warnings at all. When I run the program everything works fine until I try to assign character string data back into character string arguments that are associated with character strings in the C program.
> * Assignment of character string arguments from the C program to variables in the Basic subroutine works fine.
> * Assignment of integer results from the Basic subroutine to the integer arguments in the C program works fine.
> * BUT when I try to assign character string values to a character string argument in the C program, I get a fatal error:
> %STR-F-FATINTERR, fatal internal error
>
> I have already documented the fatal error and reported it to our firm's OpenVMS system manager who reported it to VMS Support at VSI a few minutes ago.
>
> While we are waiting for a reply from VSI, is there any way around this defect in the String module of the OpenVMS Run Time Library? Here are the procedure interfaces:
>
> C side (caller):
> void Get_DIA_Return_Eligibility ( struct dsc$descriptor_d *Customer_Location_Code_adsc, struct dsc$descriptor_d *Part_Number_adsc, long *DR3_Quantity_al, long *DR2_Quantity_al, struct dsc$descriptor_d *Oldest_Invoice_Number_adsc, struct dsc$descriptor_d *SQL_Status_adsc, struct dsc$descriptor_d *SQL_Message_adsc );
>
> Basic side (callee):
> Sub Get_DIA_Return_Eligibility ( String Customer_Location_Code_as, String Part_Number_as, Long DR3_Quantity_al, Long DR2_Quantity_al, String Oldest_Invoice_Number_as, String SQL_Status_as, String SQL_Message_as )
>
> BTW, this is NOT an academic assignment. It is a real production problem in a commercial environment with real profit and loss responsibility and real money at stake.
I think other already have answered your question.
But here is some complete code:
$ type b.bas
sub f1(string s)
print 's=' + s
end sub
sub f2(string s)
s = 'Some very long text'
end sub
$ bas b
$ type c.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <descrip.h>
#include <lib$routines.h>
void f1(struct dsc$descriptor *s);
void f2(struct dsc$descriptor *s);
int main(int argc,char *argv[])
{
struct dsc$descriptor_d ss;
struct dsc$descriptor_d ds;
char *tmp;
char *test = "Test";
int testlen = strlen(test);
ss.dsc$w_length = testlen;
ss.dsc$b_dtype = DSC$K_DTYPE_T;
ss.dsc$b_class = DSC$K_CLASS_S;
ss.dsc$a_pointer = test;
printf("call f1 with S descriptor:\n");
f1((struct dsc$descriptor *)&ss);
lib$sget1_dd(&testlen, &ds);
memcpy(ds.dsc$a_pointer, test, testlen);
printf("call f1 with D descriptor:\n");
f1((struct dsc$descriptor *)&ds);
printf("call f2 with D descriptor:\n");
printf("before length=%d pointer=%p\n", ds.dsc$w_length,
ds.dsc$a_pointer);
f2((struct dsc$descriptor *)&ds);
printf("after length=%d pointer=%p\n", ds.dsc$w_length,
ds.dsc$a_pointer);
tmp = malloc(ds.dsc$w_length + 1);
memcpy(tmp, ds.dsc$a_pointer, ds.dsc$w_length);
tmp[ds.dsc$w_length] = '\0';
printf("string = %s\n", tmp);
free(tmp);
//
return 0;
}
$ cc c
$ link c+b
$ run c
call f1 with S descriptor:
s=Test
call f1 with D descriptor:
s=Test
call f2 with D descriptor:
before length=4 pointer=34804
after length=19 pointer=34824
string = Some very long text
Arne
More information about the Info-vax
mailing list