www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - ImportC: On the issue of using a type from two different C files

reply TheGag96 <thegag96 gmail.com> writes:
I've been trying out ImportC with libgit2 lately, and it's 
honestly a bit like magic!! Kudos to Walter for his work so far - 
this has been really cool. However, you may have seen Adam's 
[blog 
post](http://dpldocs.info/this-week-in-d/Blog.Posted_2022_05_16.html#importc-an
-module-namespaces) about the issue that D's module namespaces create, where a
type imported from two different .c files aren't compatible with each other.
There's a [Bugzilla issue](https://issues.dlang.org/show_bug.cgi?id=22674)
about it too, which Walter initially closed as WONTFIX because it seemed like
it needed too difficult a fix.

Zig advertises a similarly "magic" C importing feature. I made 
[an example](https://github.com/TheGag96/zigwithc) trying a 
similar scenario to what Adam described, and it seems we're 
actually in "good company":


```
<proj path>/src/main.zig:11:16: error: expected type 
'.media.<username>.4ea9c2fa-455c-480d-adbd-b533afd47647.home.<username>.Coding.Zig.zigwithc.zig-cache.o.8cf07da78935aad995196c635ddb6192
cimport.struct_tm', found
'.media.<username>.4ea9c2fa-455c-480d-adbd-b533afd47647.home.<username>.Coding.Zig.zigwithc.zig-cache.o.46100012acc16f9e9848385e1fd2122e.cimport.struct_tm'
     clibB.doIt(thing);
                ^~~~~
<proj 
path>/zig-cache/o/46100012acc16f9e9848385e1fd2122e/cimport.zig:121:30: note:
struct declared here
pub const struct_tm = extern struct {
                       ~~~~~~~^~~~~~
<proj 
path>/zig-cache/o/8cf07da78935aad995196c635ddb6192/cimport.zig:121:30: note:
struct declared here
pub const struct_tm = extern struct {
                       ~~~~~~~^~~~~~
```

I'd like to know how they plan to solve this issue themselves... 
Maybe we can help each other out in this regard.

I asked Adam about it on the Discord, and his suggestion was:

 but there is a pretty easy solution to this in any case: make 
 everything from importC be an alias back into an 
 implicitly-created global namespace
What do you think? This at least seems like a sound idea.
Aug 26 2022
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Saturday, 27 August 2022 at 02:34:39 UTC, TheGag96 wrote:


 What do you think?
This has been discussed a couple of times in our Foundation meetings. The most recent was in May. See Walter's section in the sumamry: https://forum.dlang.org/thread/uhgndrcnekedjqtarnwl forum.dlang.org Iain suggested the following:
 ImportC symbols, rather than going into a module space, should 
 go into a global ImportC module. Each imported C file or header 
 file is then appended to that module.
Martin disagreed, and proposed an alternative:
 Martin said that one problem with that approach is that a D 
 module would have access to symbols it didn't import. He 
 suggested the ideal solution would be for each header to have 
 its own module that doesn't change from one invocation of the 
 compiler to the next.
Aug 26 2022
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Saturday, 27 August 2022 at 03:07:25 UTC, Mike Parker wrote:
 Martin disagreed, and proposed an alternative:

 Martin said that one problem with that approach is that a D 
 module would have access to symbols it didn't import. He 
 suggested the ideal solution would be for each header to have 
 its own module that doesn't change from one invocation of the 
 compiler to the next.
This pretty much requires DMD to incorporate a C preprocessor, right? Since that's the only way it can reliably determine which headers are included.
Aug 26 2022
prev sibling next sibling parent Dave P. <dave287091 gmail.com> writes:
On Saturday, 27 August 2022 at 03:07:25 UTC, Mike Parker wrote:
 On Saturday, 27 August 2022 at 02:34:39 UTC, TheGag96 wrote:


 What do you think?
This has been discussed a couple of times in our Foundation meetings. The most recent was in May. See Walter's section in the sumamry: https://forum.dlang.org/thread/uhgndrcnekedjqtarnwl forum.dlang.org Iain suggested the following:
 ImportC symbols, rather than going into a module space, should 
 go into a global ImportC module. Each imported C file or 
 header file is then appended to that module.
Martin disagreed, and proposed an alternative:
 Martin said that one problem with that approach is that a D 
 module would have access to symbols it didn't import. He 
 suggested the ideal solution would be for each header to have 
 its own module that doesn't change from one invocation of the 
 compiler to the next.
IMO, the best solution is to implement some variation of C23’s rules for tag compatibility where identical types with identical tags are treated as equivalent. Importing into a global C namespace means you can’t use two C headers with conflicting definitions of a type. Ideally, using C from D should be better than using C from C and allow you to resolve this situation via the module system while still allowing you to mix compatible types between C modules.
Aug 26 2022
prev sibling parent Adam D Ruppe <destructionator gmail.com> writes:
On Saturday, 27 August 2022 at 03:07:25 UTC, Mike Parker wrote:
 Martin disagreed, and proposed an alternative:

 Martin said that one problem with that approach is that a D 
 module would have access to symbols it didn't import. He 
 suggested the ideal solution would be for each header to have 
 its own module that doesn't change from one invocation of the 
 compiler to the next.
This is why I said "be an alias" in the chat thread. The `import c` module essentially selectively imports just the things actually declared from the magic module, giving the same behavior, but since the canonical name+definition is elsewhere and merged in there, the aliases won't cause type conflicts. The implementation might be easier said than done, since you'd have a pseudo-module being mutated through the import process. I expect a high probability of forward reference bugs cropping up. But the concept is something we can test by hand. Taking the same example from my blog that fails with importC on dmd master an doing instead: --- module __magic_importC; // representing all the C definitions imported struct FILE; extern(C) int printf(const char*, ...); extern(C) int fclose(FILE*); extern(C) void saySomethingToAFile(FILE*); extern(C) FILE* openAFile(); --- then --- module b; // it does a public selective import public import magic : FILE, printf, fclose, openAFile; --- and --- module b2; // again public selective import public import magic : FILE, printf, fclose, saySomethingToAFile; --- And now the test program compiles successfully: --- import b; import b2; void main() { auto fp = openAFile(); scope(exit) fclose(fp); saySomethingToAFile(fp); printf("Hello\n"); } --- and if you remove an import, you correctly get: d.d(7): Error: undefined identifier `saySomethingToAFile` thanks to the selective import mechanism. This scheme is compatible with both C and D declaration rules, doesn't have a big namespace surprise (the compiler should also just forbid importing the magic internal implementation module so people don't try to poke that directly), and.... might be doable. Again, possibility of bugs with the extraordinary magic module being mutated through the process, but since that's all inside dmd thanks to the selective import hiding anything you can't see in the right order anyway and the mutations are strictly additive we ought to be able to cover it up and make it work.
Aug 27 2022
prev sibling parent TheGag96 <thegag96 gmail.com> writes:
I asked the Zig Discord about their plans. Andrew Kelley himself 
actually responded:

 projects should try to have only 1 c import for all C 
 interfacing
So they're satisfied, at least for the moment, with how things work now. Hopefully D can solve it the most satisfyingly. ImportC is a great feature for D, I think.
Aug 26 2022