On Monday, 26 February 2018 at 17:54:12 UTC, H. S. Teoh wrote:
What's the correct translation of the following C declarations into D?

        typedef double[1] mytype;

This isn't valid C, but `typedef double mytype[1];` is.


        void someFunc(mytype x, mytype *y, mytype **z);

        struct SomeStruct {
                mytype x;
                mytype *y;
                mytype **z;
        }

I need this to interface with an external C library. Currently, I just wrapped the above as-is inside an extern(C) block. But I suspect it may be wrong, because:

1) In C, declaring a function parameter of type double[1] is, IIRC, the same thing as declaring it as double*. But in D, double[1] passes one double by value as a static array. So there may be an API mismatch here.

Yes, a `double[1]` parameter in C and `double*` are the same thing. However, that's not valid for the other two parameters (y and z).

There's a common misconception in C that arrays and pointers are the same thing - they're not. This comes about because of the dubious C feature whereby arrays decay into pointers in function calls. Somewhat related to this, a little known feature of C is pointers to arrays. In your example, that's what y and z are. They have funky syntax and look like function pointers, unless they're obscured with a typedef as in your example.

You can pass a double array of any size to x, or a pointer to double, but y and z are constrained to be pointers to arrays of size 1. Exemplified:

    typedef double mytype[1];
    void func1(mytype x);
    void func2(mytype* x);

    int main() {
        double arr1[1];
        double arr2[2];
        double* ptr;

        func1(arr1); // fine
        func1(arr2); // fine
        func1(ptr);  // fine

        func2(&arr1); // fine
        func2(&arr2); // oops - won't compile
    }




2) In C, declaring a *variable* or struct field as double[1] has essentially the same semantics as D's static arrrays. Meaning that I cannot just change the declaration of mytype in order to get the correct behaviour of function parameters.

3) I'm getting a segfault at runtime of some C++ code into D, that calls the library via this C API, and I suspect it's probably due to (1).

The correct translation is:

extern(C) void someFunc(double* x, double[1]* y, double[1]** z);


Atila

Reply via email to