DPP: Linker issue with functions implemented in C header files

Petar Petar
Tue Feb 18 10:23:22 UTC 2020


On Tuesday, 18 February 2020 at 09:20:08 UTC, Andre Pany wrote:
>
> Hi Petar,

Hi Andre, I'm happy to help :)

> thank you very much for the explanation and the code sample.
> Filling the az_span anonymous member was the tricky part,
> I thought it would be not possible to do so, but you showed me
> the trick.

I wouldn't call it a trick, I was using standard struct literal 
initialization (the very syntax that DIP1031 proposes to 
deprecate).

For example:

struct Inner { int x, y; }
struct Outer { Inner inner; }

// You can initialize Outer in various ways:

// 1)
auto o1 = Outer(Inner(1, 2));

// 2)
Outer o2 = { inner: Inner(1, 2) };

// 3)
Outer o3 = { Inner(1, 2) };

// 4)
Outer o4 = { inner: { x: 1, y: 2} };

// 5)
Outer o5 = { { x: 1, y: 2} };

// 6)
Outer o6;
o6.inner.x = 1;
o6.inner.y = 1;

For POD (plain old data) struct like that, all six variants are 
equivalent (of course there more possible variations).

Since there's no `private` protection modifier in C, the only 
thing C library authors can do is make it inconvenient to access 
struct fields (by prefixing them with underscores), but they 
can't really prevent it.

For example, without this syntax, in pure C you can initialize a 
span like this:
char my_string[] = "Hey";
az_span span;
span._internal.ptr = my_string;
span._internal.length = sizeof(my_string) - 1;
span._internal.capacity = sizeof(my_string) - 1;

And with almost the same syntax you can do this in D:

string my_string = "Hey";
az_span span;
span._internal.ptr = cast(ubyte*)my_string.ptr; // note: I think 
this should be safe, because of [1]
span._internal.length = my_string.length;
span._internal.capacity = my_string.length;

It's just that that author wanted to prevent accidental bugs by 
pushing you to use the inline helper functions or macros (which 
are technically not needed).

[1]: 
https://github.com/Azure/azure-sdk-for-c/blob/25f8a0228e5f250c02e389f19d88c064c93959c1/sdk/core/core/inc/az_span.h#L22


> I will do it like you have proposed but had also already created
> a ticket for the Azure SDK developer:
> https://github.com/Azure/azure-sdk-for-c/issues/359
> There should be a more convenient way to fill a az_span 
> structure.

To be honest, I don't think the authors will agree to change 
this, as putting inline functions in headers files is a pretty 
common practice in both C and C++.
There are two benefits to that:
1) Potentially better performance, because the code is easier to 
inline
2) It's possible to provide header-only libraries (not the case 
here), that don't require build steps.

> For reference, here is my dockerfile which does the DPP call 
> and linking:

Cool, I'll check it later!

> ``` dockerfile
> FROM dlang2/ldc-ubuntu:1.20.0 as ldc
>
> RUN apt-get install -y git libssl-dev uuid-dev 
> libcurl4-openssl-dev curl
>
> RUN curl -OL 
> https://cmake.org/files/v3.12/cmake-3.12.4-Linux-x86_64.sh \
>     && mkdir /opt/cmake \
>     && sh /cmake-3.12.4-Linux-x86_64.sh --prefix=/opt/cmake 
> --skip-license \
>     && ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake
>
> RUN git clone https://github.com/Azure/azure-sdk-for-c.git \
>     && cd azure-sdk-for-c \
>     && git submodule update --init --recursive
>
> RUN cd azure-sdk-for-c \
>     && mkdir build \
>     && cd build \
>     && cmake ../ \
>     && make
>
> RUN apt-get install -y clang-9 libclang-9-dev
> RUN ln -s /usr/bin/clang-9 /usr/bin/clang
> COPY az_storage_blobs.dpp /tmp/
>
> RUN DFLAGS="-L=-L/usr/lib/llvm-9/lib/" dub run dpp -- --help
>
> RUN DFLAGS="-L=-L/usr/lib/llvm-9/lib/" dub run dpp -- 
> /tmp/az_storage_blobs.dpp \
>     --include-path /azure-sdk-for-c/sdk/core/core/inc \
>     --include-path /azure-sdk-for-c/sdk/core/core/internal \
>     --include-path /azure-sdk-for-c/sdk/storage/blobs/inc \
>     --include-path 
> /azure-sdk-for-c/sdk/transport_policies/curl/inc \
>     --preprocess-only
>
> ADD blobs_client_example.d /tmp/blobs_client_example.d
> RUN  ldc2 /tmp/blobs_client_example.d /tmp/az_storage_blobs.d \
>     /azure-sdk-for-c/build/sdk/core/core/libaz_core.a \
>     
> /azure-sdk-for-c/build/sdk/storage/blobs/libaz_storage_blobs.a \
>     
> /azure-sdk-for-c/build/sdk/transport_policies/curl/libaz_curl.a 
> \
>     -of=/tmp/app
> ```
>
> Kind regards
> André

Cheers,
Petar


More information about the Digitalmars-d-learn mailing list