Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

camlidl: some array-related problems #2884

Closed
vicuna opened this issue Aug 1, 2001 · 4 comments
Closed

camlidl: some array-related problems #2884

vicuna opened this issue Aug 1, 2001 · 4 comments

Comments

@vicuna
Copy link

vicuna commented Aug 1, 2001

Original bug ID: 467
Reporter: administrator
Status: closed
Resolution: fixed
Priority: normal
Severity: minor
Category: -for CamlIDL use https://github.com/xavierleroy/camlidl/issues

Bug description

  1. In contrast with what the manual says, "unique" attribute is not
    applicable to arrays and should be ignored (array is not l-value and cannot
    be equal to NULL). Currently incorrect C-code is generated:

typedef struct
{
int len;
[length_is(len),unique] char data[10];
} Array1;

|
V

typedef struct {
int len;
char data[10];
} Array1;

void camlidl_ml2c_array_Array1(value _v1, Array1 * _c2, camlidl_ctx _ctx)
{
value _v3;
mlsize_t _c4;
mlsize_t _c5;
value _v6;
if (_v1 == Val_int(0)) {
(_c2).data = NULL; / syntax error, data is not l-value! /
} else {
_v3 = Field(_v1, 0);
_c4 = Wosize_val(_v3);
if (_c4 != 10) invalid_argument("typedef Array1");
for (_c5 = 0; _c5 < 10; _c5++) {
_v6 = Field(_v3, _c5);
(
_c2).data[_c5] = Int_val(_v6);
}
}
}

  1. It's impossible to create bigarray of the fixed size -- pointer (not
    array) is always created:

typedef struct
{
int len;
[length_is(len)] int data[10];
} Array2;

typedef struct
{
int len;
[length_is(len),bigarray] int data[10];
} BigArray;

|
V

typedef struct
{
int len;
int data[10];
} Array2;

typedef struct {
int len;
int data; / why not data[10]? */
} BigArray;

  1. Arrays of non-specified size are treated as pointers, but MIDL treats
    them differently:

typedef struct
{
int len;
[size_is(len)] int data[];
} Array3;

|
V

camlidl:

typedef struct {
int len;
int *data;
} Array3;

midl:

typedef /* [public] / struct __MIDL___MIDL_itf_array_0000_0002
{
int len;
/
[length_is] */ int data[ 1 ];
} Array3;

I would prefer the MIDL way, because otherwise we cannot properly describe
C-structures where array (not pointer) is used, but its size is not
known. Of course, these arrays can only be used as [in] parameters, and
ML->C conversion functions should not be generated (if we need [out]
structure, we should use pointer, not array).

Hope to hear from you soon,
Dmitry

@vicuna
Copy link
Author

vicuna commented Aug 8, 2001

Comment author: administrator

  1. In contrast with what the manual says, "unique" attribute is not
    applicable to arrays and should be ignored (array is not l-value and cannot
    be equal to NULL).

You mean, unlike in the following C code? :-)

void f(int x[])
{
x = NULL;
}

More seriously: CamlIDL maps IDL arrays to C arrays when a
compile-time size is given (int data[10]), and to C pointers (to arrays)
otherwise (int data[]). This mimicks pretty much exactly what C does
with array function parameters.

Currently incorrect C-code is generated:

typedef struct
{
int len;
[length_is(len),unique] char data[10];
} Array1;

Yes, "unique" isn't applicable to arrays with a compile-time size.
Just don't do that :-) (I'll add code to detect this error.)

  1. It's impossible to create bigarray of the fixed size -- pointer (not
    array) is always created:

Correct. I guess it should be possible to map them to C arrays when
all dimensions are known at compile-time. Or even when all dimensions
except the major one are known. I'll look into that.

  1. Arrays of non-specified size are treated as pointers, but MIDL treats
    them differently:
    midl:
    typedef /* [public] / struct __MIDL___MIDL_itf_array_0000_0002
    {
    int len;
    /
    [length_is] */ int data[ 1 ];
    } Array3;

That's a lot more problematic. For one thing, this is not valid ANSI C --
more precisely, accessing an element of Array3.data beyond the 0-th
element results in undefined behavior. Yes, it usually works, but still.
Second, as you say:

I would prefer the MIDL way, because otherwise we cannot properly describe
C-structures where array (not pointer) is used, but its size is not
known. Of course, these arrays can only be used as [in] parameters, and
ML->C conversion functions should not be generated (if we need [out]
structure, we should use pointer, not array).

The way CamlIDL is currently set up makes it very hard to have
conversions in only one direction. In particular, each struct
or typedef declaration must generate conversion functions in both
directions -- the code generated by CamlIDL is modular, in the sense
that conversions for named types are factored out as functions rather
than being expanded at point of use. Handling this properly would
require quite a lot of work...

  • Xavier Leroy

@vicuna vicuna closed this as completed Aug 8, 2001
@vicuna
Copy link
Author

vicuna commented Aug 8, 2001

Comment author: administrator

A follow-up to my previous reply:

  1. It's impossible to create bigarray of the fixed size -- pointer (not
    array) is always created:

A strong reason for doing this is that Caml bigarrays are designed so
that there is no data copying when converting between Caml and C.
This property can only be preserved if the bigarray is always
represented by a pointer in C -- if it's a C fixed-size array, some
copying is required. On the other hand, regular Caml arrays are
always copied between C and Caml. So, why is it that you'd need a
fixed-size bigarray -- isn't just an ordinary array sufficient?

  • Xavier Leroy

@vicuna
Copy link
Author

vicuna commented Aug 29, 2001

Comment author: administrator

Xavier Leroy Xavier.Leroy@inria.fr writes:

First of all, I apologize for the very long delay.

  1. In contrast with what the manual says, "unique" attribute is not
    applicable to arrays and should be ignored (array is not l-value and cannot
    be equal to NULL).

You mean, unlike in the following C code? :-)

void f(int x[])
{
x = NULL;
}

More seriously: CamlIDL maps IDL arrays to C arrays when a
compile-time size is given (int data[10]), and to C pointers (to arrays)
otherwise (int data[]). This mimicks pretty much exactly what C does
with array function parameters.

For functions yes, but we are talking of structures. Obviously, C
structures have different memory layout for pointer and array fields.

Currently incorrect C-code is generated:

typedef struct
{
int len;
[length_is(len),unique] char data[10];
} Array1;

Yes, "unique" isn't applicable to arrays with a compile-time size.
Just don't do that :-) (I'll add code to detect this error.)

OK.

  1. It's impossible to create bigarray of the fixed size -- pointer (not
    array) is always created:

Correct. I guess it should be possible to map them to C arrays when
all dimensions are known at compile-time. Or even when all dimensions
except the major one are known. I'll look into that.

  1. Arrays of non-specified size are treated as pointers, but MIDL treats
    them differently:
    midl:
    typedef /* [public] / struct __MIDL___MIDL_itf_array_0000_0002
    {
    int len;
    /
    [length_is] */ int data[ 1 ];
    } Array3;

That's a lot more problematic. For one thing, this is not valid ANSI C --
more precisely, accessing an element of Array3.data beyond the 0-th
element results in undefined behavior. Yes, it usually works, but still.

Second, as you say:

I would prefer the MIDL way, because otherwise we cannot properly describe
C-structures where array (not pointer) is used, but its size is not
known. Of course, these arrays can only be used as [in] parameters, and
ML->C conversion functions should not be generated (if we need [out]
structure, we should use pointer, not array).

The way CamlIDL is currently set up makes it very hard to have
conversions in only one direction. In particular, each struct
or typedef declaration must generate conversion functions in both
directions -- the code generated by CamlIDL is modular, in the sense
that conversions for named types are factored out as functions rather
than being expanded at point of use. Handling this properly would
require quite a lot of work...

Then we should prohibit using (int data[]) for now as non-supported
construct and force the user to use (int *data) in his/her code
instead. IMHO, implementing it different way than MIDL is simply not
acceptable -- we will easily have binary incompatibility under Windows in
that case.

And second, (int data[]) construct implemented as the data[1] array
sometimes is really useful. E.g., I do not know other way to define the
function like free(), taking a memory block with the header, indicating its
size.

Hope to hear from you soon,
Dmitry

@vicuna
Copy link
Author

vicuna commented Aug 29, 2001

Comment author: administrator

Xavier Leroy Xavier.Leroy@inria.fr writes:

  1. It's impossible to create bigarray of the fixed size -- pointer (not
    array) is always created:

A strong reason for doing this is that Caml bigarrays are designed so
that there is no data copying when converting between Caml and C.
This property can only be preserved if the bigarray is always
represented by a pointer in C -- if it's a C fixed-size array, some
copying is required. On the other hand, regular Caml arrays are
always copied between C and Caml. So, why is it that you'd need a
fixed-size bigarray -- isn't just an ordinary array sufficient?

You are right. But it just means that

[bigarray] int data[something or empty];

should be prohibited and the "bigarray" attribute is applicable only to
pointers.

Hope to hear from you soon,
Dmitry

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant