January 01, 2024
https://issues.dlang.org/show_bug.cgi?id=24312

          Issue ID: 24312
           Summary: importC: Document workaround for using C symbols which
                    are also D keywords
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: andrej.mitrovich@gmail.com

I might make a PR for this later, but I'm keeping this as a placeholder.

Initially this was going to be a bug report but I found a neat workaround.

This is similar to https://issues.dlang.org/show_bug.cgi?id=23004, except it's about calling C code on the D side.

clap.c:
-----
typedef struct clap_host {
   const char *version;
} clap_host_t;

typedef struct clap_plugin_entry {
    void (*init)(const char *plugin_path);
} clap_plugin_entry_t;
-----

And two separate test-cases. They're separate because the error in the first test-case makes the second test-case error disappear (short-circuit of errors I guess):

test1.d:
-----
import clap;

void main() {
    clap_host* host;
    host.version = null;
}
-----

test2.d:
-----
import clap;

void main() {
    clap_plugin_entry* entry;
    entry.init(null);
}
-----

```
$ dmd -c test1.d clap.c
test1.d(5): Error: identifier or `new` expected following `.`, not `version`

$ dmd -c test2.d clap.c
test.d(5): Error: function expected before `()`, not `null` of type
`clap_plugin_entry*
```

I understand this can't be allowed since it's semantically invalid D code.

There is however a workaround using the getMember trait:

```
import clap;

void main() {
    clap_plugin_entry* entry;
    __traits(getMember, *entry, "init")(null);

    clap_host* host;
    __traits(getMember, *host, "version") = null;
}
```

I think it would be good to document this workaround on the ImportC page: https://dlang.org/spec/importc.html

--