www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Cannot compile C file using ImportC

reply rempas <rempas tutanota.com> writes:
So I'm trying to compile the 
[toml99](https://github.com/cktan/tomlc99) C library with DMD 
using ImportC. I first preprocessed the file using `cproc`. The 
reason I didn't used GCC is because it defines some symbols 
specific to GCC so it will furthermore mess the compilation 
process. I created a gist of the file and uploaded 
[here](https://gist.github.com/rempas/a1633ba4d3fd4f166277d7ff35cedc63) in case
someone wants to get the file and try it. The error message I'm getting is the
following:

```
toml.c(39): Error: cannot implicitly convert expression `malloc` 
of type `extern (C) void*(ulong __size)` to `extern (C) void* 
function(ulong)`
toml.c(40): Error: cannot implicitly convert expression `free` of 
type `extern (C) void(void* __ptr)` to `extern (C) void 
function(void*)`
```

These two symbols are function pointers but I wasn't able to 
modify and make it work. Any ideas?
Nov 09 2021
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/9/21 6:45 AM, rempas wrote:
 So I'm trying to compile the [toml99](https://github.com/cktan/tomlc99) 
 C library with DMD using ImportC. I first preprocessed the file using 
 `cproc`. The reason I didn't used GCC is because it defines some symbols 
 specific to GCC so it will furthermore mess the compilation process. I 
 created a gist of the file and uploaded 
 [here](https://gist.github.com/rempas/a1633ba4d3fd4f166277d7ff35cedc63) 
 in case someone wants to get the file and try it. The error message I'm 
 getting is the following:
 
 ```
 toml.c(39): Error: cannot implicitly convert expression `malloc` of type 
 `extern (C) void*(ulong __size)` to `extern (C) void* function(ulong)`
 toml.c(40): Error: cannot implicitly convert expression `free` of type 
 `extern (C) void(void* __ptr)` to `extern (C) void function(void*)`
 ```
 
 These two symbols are function pointers but I wasn't able to modify and 
 make it work. Any ideas?
It seems like it should work. Figuring out the "lines" for things is really difficult in this expanded format, even though I know why it does that. I think importC should possibly allow printing of the actual source line along with the explicit source file/line, because knowing the vagrancies of the preprocessor is not going to be something that's easy to deal with, and you want to see what raw format is being passed to the compiler. [here](https://gist.github.com/rempas/a1633ba4d3fd4f166277d7ff35cedc63 file-tomld-c-L1439) is where "line 39" of toml.c is. [here](https://gist.github.com/rempas/a1633ba4d3fd4f166277d7ff35cedc6 #file-tomld-c-L763) is where the definition of `malloc` is. To me, this looks reasonable. I narrowed it down to the following file, and it builds with gcc and ldc2 on my system. I don't have support for DMD, as this is an Arm system, but on another system, I can confirm that DMD 2.098.0 does not compile this: ```c typedef long unsigned int size_t; extern void *malloc (size_t __size) ; static void* (*ppmalloc)(size_t) = malloc; ``` I used `dmd -c testc.c`, `gcc -c testc.c` and `ldc2 -c testc.c`. Please file a bug report. https://issues.dlang.org -Steve
Nov 09 2021
parent reply rempas <rempas tutanota.com> writes:
On Tuesday, 9 November 2021 at 13:44:04 UTC, Steven Schveighoffer 
wrote:
 It seems like it should work. Figuring out the "lines" for 
 things is really difficult in this expanded format, even though 
 I know why it does that. I think importC should possibly allow 
 printing of the actual source line along with the explicit 
 source file/line, because knowing the vagrancies of the 
 preprocessor is not going to be something that's easy to deal 
 with, and you want to see what raw format is being passed to 
 the compiler.

 [here](https://gist.github.com/rempas/a1633ba4d3fd4f166277d7ff35cedc63
file-tomld-c-L1439) is where "line 39" of toml.c is.
 [here](https://gist.github.com/rempas/a1633ba4d3fd4f166277d7ff35cedc6
#file-tomld-c-L763) is where the definition of `malloc` is.

 To me, this looks reasonable. I narrowed it down to the 
 following file, and it builds with gcc and ldc2 on my system. I 
 don't have support for DMD, as this is an Arm system, but on 
 another system, I can confirm that DMD 2.098.0 does not compile 
 this:

 ```c
 typedef long unsigned int size_t;
 extern void *malloc (size_t __size)
      ;
 static void* (*ppmalloc)(size_t) = malloc;
 ```

 I used `dmd -c testc.c`, `gcc -c testc.c` and `ldc2 -c testc.c`.

 Please file a bug report.

 https://issues.dlang.org

 -Steve
It works with LDC2 for you? I'm having the latest version (ldc 1.28.0) downloaded from the [release](https://github.com/ldc-developers/ldc/releases/tag/v1.28.0) page for Linux (X86_64) and it doesn't seem to work for me. These 2 errors are not present with LDC2 however, I'm now getting some other errors with LDC2. How was your LDC2 built? Also it is worth noting that the compiler that is used to preprocess the file will result in different error messages when trying to use ImportC. For example when using cproc to preprocess and then LDC2 to compile, the error message is the following: ``` toml.c(638): Error: assignment cannot be used as a condition, perhaps `==` was meant? toml.c(671): Error: assignment cannot be used as a condition, perhaps `==` was meant? toml.c(1027): Error: assignment cannot be used as a condition, perhaps `==` was meant? toml.c(1140): Error: assignment cannot be used as a condition, perhaps `==` was meant? toml.c(1844): Error: cannot implicitly convert expression `*((*tab).arr + cast(long)i * 8L)` of type `const(toml_array_t*)` to `toml_array_t*` toml.c(1855): Error: cannot implicitly convert expression `*((*tab).tab + cast(long)i * 8L)` of type `const(toml_table_t*)` to `toml_table_t*` toml.c(1914): Error: cannot implicitly convert expression `0 <= idx && (idx < (*arr).nitem) ? (*((*arr).item + cast(long)idx * 32L)).arr : cast(const(toml_array_t*))0LU` of type `const(toml_array_t*)` to `toml_array_t*` toml.c(1919): Error: cannot implicitly convert expression `0 <= idx && (idx < (*arr).nitem) ? (*((*arr).item + cast(long)idx * 32L)).tab : cast(const(toml_table_t*))0LU` of type `const(toml_table_t*)` to `toml_table_t*` toml.c(2247): Error: assignment cannot be used as a condition, perhaps `==` was meant? toml.c(2305): Error: assignment cannot be used as a condition, perhaps `==` was meant? ``` When preprocessing with GCC, both DMD and LDC give the same error message and it the same I've got from another time I tried to use ImportC and it is [here](https://forum.dlang.org/post/sacokknyeqqsayxoudop forum.dlang.org). Clang has the same behavior as well. When preprocessing with TCC, again both of them have the same error message and it's the following: ``` /usr/include/stdio.h(407): Error: missing comma /usr/include/stdio.h(407): Error: `=`, `;` or `,` expected /usr/include/stdio.h(410): Error: missing comma /usr/include/stdio.h(410): Error: `=`, `;` or `,` expected /usr/include/stdio.h(412): Error: missing comma /usr/include/stdio.h(412): Error: `=`, `;` or `,` expected /usr/include/stdio.h(451): Error: missing comma /usr/include/stdio.h(451): Error: `=`, `;` or `,` expected /usr/include/stdio.h(456): Error: missing comma /usr/include/stdio.h(456): Error: `=`, `;` or `,` expected /usr/include/stdio.h(459): Error: missing comma /usr/include/stdio.h(459): Error: `=`, `;` or `,` expected /usr/include/string.h(410): Error: missing comma /usr/include/string.h(410): Error: `=`, `;` or `,` expected ``` I haven't tried to preprocess with any other compilers but I don't expect anything else to work if these didn't...
Nov 09 2021
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/10/21 2:04 AM, rempas wrote:
 On Tuesday, 9 November 2021 at 13:44:04 UTC, Steven Schveighoffer wrote:
 It seems like it should work. Figuring out the "lines" for things is 
 really difficult in this expanded format, even though I know why it 
 does that. I think importC should possibly allow printing of the 
 actual source line along with the explicit source file/line, because 
 knowing the vagrancies of the preprocessor is not going to be 
 something that's easy to deal with, and you want to see what raw 
 format is being passed to the compiler.

 [here](https://gist.github.com/rempas/a1633ba4d3fd4f166277d7ff35cedc63
file-tomld-c-L1439) 
 is where "line 39" of toml.c is.
 [here](https://gist.github.com/rempas/a1633ba4d3fd4f166277d7ff35cedc6
#file-tomld-c-L763) 
 is where the definition of `malloc` is.

 To me, this looks reasonable. I narrowed it down to the following 
 file, and it builds with gcc and ldc2 on my system. I don't have 
 support for DMD, as this is an Arm system, but on another system, I 
 can confirm that DMD 2.098.0 does not compile this:

 ```c
 typedef long unsigned int size_t;
 extern void *malloc (size_t __size)
      ;
 static void* (*ppmalloc)(size_t) = malloc;
 ```

 I used `dmd -c testc.c`, `gcc -c testc.c` and `ldc2 -c testc.c`.

 Please file a bug report.

 https://issues.dlang.org
It works with LDC2 for you? I'm having the latest version (ldc 1.28.0) downloaded from the [release](https://github.com/ldc-developers/ldc/releases/tag/v1.28.0) page for Linux (X86_64) and it doesn't seem to work for me. These 2 errors are not present with LDC2 however, I'm now getting some other errors with LDC2. How was your LDC2 built?
I'm using the downloaded LDC2 for aarch64. But I'm not building tomld.c that you created, I'm building the reduced example (that I posted).
 Also it is worth noting that the compiler that is used to preprocess the 
 file will result in different error messages when trying to use ImportC. 
 For example when using cproc to preprocess and then LDC2 to compile, the 
 error message is the following:
 
 ```
 toml.c(638): Error: assignment cannot be used as a condition, perhaps 
 `==` was meant?
 toml.c(671): Error: assignment cannot be used as a condition, perhaps 
 `==` was meant?
 toml.c(1027): Error: assignment cannot be used as a condition, perhaps 
 `==` was meant?
 toml.c(1140): Error: assignment cannot be used as a condition, perhaps 
 `==` was meant?
 toml.c(1844): Error: cannot implicitly convert expression `*((*tab).arr 
 + cast(long)i * 8L)` of type `const(toml_array_t*)` to `toml_array_t*`
 toml.c(1855): Error: cannot implicitly convert expression `*((*tab).tab 
 + cast(long)i * 8L)` of type `const(toml_table_t*)` to `toml_table_t*`
 toml.c(1914): Error: cannot implicitly convert expression `0 <= idx && 
 (idx < (*arr).nitem) ? (*((*arr).item + cast(long)idx * 32L)).arr : 
 cast(const(toml_array_t*))0LU` of type `const(toml_array_t*)` to 
 `toml_array_t*`
 toml.c(1919): Error: cannot implicitly convert expression `0 <= idx && 
 (idx < (*arr).nitem) ? (*((*arr).item + cast(long)idx * 32L)).tab : 
 cast(const(toml_table_t*))0LU` of type `const(toml_table_t*)` to 
 `toml_table_t*`
 toml.c(2247): Error: assignment cannot be used as a condition, perhaps 
 `==` was meant?
 toml.c(2305): Error: assignment cannot be used as a condition, perhaps 
 `==` was meant?
 ```
That is an interesting situation -- you have D errors being applied to C code. I think those should be disabled, otherwise, you will have to change all your C code, and it's more like portC than importC. I'd suggest filing all these as issues. If importC is to be successful it has to build existing C projects. -Steve
Nov 10 2021
parent reply rempas <rempas tutanota.com> writes:
On Wednesday, 10 November 2021 at 15:04:35 UTC, Steven 
Schveighoffer wrote:
 I'm using the downloaded LDC2 for aarch64.

 But I'm not building tomld.c that you created, I'm building the 
 reduced example (that I posted).
How? What's the difference in your example? How you preprocessed and compiled?
 That is an interesting situation -- you have D errors being 
 applied to C code. I think those should be disabled, otherwise, 
 you will have to change all your C code, and it's more like 
 portC than importC.

 I'd suggest filing all these as issues. If importC is to be 
 successful it has to build existing C projects.

 -Steve
I did! I personally believe that ImportC is the last and only chance for D. More and more people seem to abandon D libraries so more people leave and less people are coming because of that. At the same time because there are not a lot of people, there are not a lot of libraries and more get abandoned. It's actually a cycle. ImportC can be a true game changer!!!
Nov 10 2021
next sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Wednesday, 10 November 2021 at 17:38:12 UTC, rempas wrote:
 On Wednesday, 10 November 2021 at 15:04:35 UTC, Steven 
 Schveighoffer wrote:
 [...]
How? What's the difference in your example? How you preprocessed and compiled?
 [...]
I did! I personally believe that ImportC is the last and only chance for D. More and more people seem to abandon D libraries so more people leave and less people are coming because of that. At the same time because there are not a lot of people, there are not a lot of libraries and more get abandoned. It's actually a cycle. ImportC can be a true game changer!!!
Agreed. But, it must be quite seamless. But if we could get there, yes 🌟
Nov 10 2021
parent rempas <rempas tutanota.com> writes:
On Wednesday, 10 November 2021 at 17:57:50 UTC, Imperatorn wrote:
 Agreed. But, it must be quite seamless. But if we could get 
 there, yes 🌟
It should be able to compile medium to big libraries. Nobody excepts it to be able to compile GIMP but it should be a able to tomlc99 which is a little bit more than 2k lines of code
Nov 10 2021
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/10/21 12:38 PM, rempas wrote:
 On Wednesday, 10 November 2021 at 15:04:35 UTC, Steven Schveighoffer wrote:
 I'm using the downloaded LDC2 for aarch64.

 But I'm not building tomld.c that you created, I'm building the 
 reduced example (that I posted).
How? What's the difference in your example? How you preprocessed and compiled?
I did none of that. My example is the lines you had problems with, and only enough to make that error show up. It's just those 3 lines.
 
 I did! I personally believe that ImportC is the last and only chance for 
 D. More and more people seem to abandon D libraries so more people leave 
 and less people are coming because of that. At the same time because 
 there are not a lot of people, there are not a lot of libraries and more 
 get abandoned. It's actually a cycle. ImportC can be a true game changer!!!
I don't think ImportC is that much of a game changer (you can already make C bindings with quite a small effort, and there are tools to get you 90% there), but a broken/not working ImportC will be a huge drawback to the language, so it's important to get it right. -Steve
Nov 10 2021
next sibling parent rempas <rempas tutanota.com> writes:
On Thursday, 11 November 2021 at 02:03:22 UTC, Steven 
Schveighoffer wrote:
 I don't think ImportC is that much of a game changer (you can 
 already make C bindings with quite a small effort, and there 
 are tools to get you 90% there), but a broken/not working 
 ImportC will be a huge drawback to the language, so it's 
 important to get it right.

 -Steve
Actually you are right, there are ways to do that but having a FULLY working C compiler that will be able to do ALL the work for you will be awesome! But maybe yeah you are right, it will probably not be a game changer
Nov 10 2021
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 11 November 2021 at 02:03:22 UTC, Steven 
Schveighoffer wrote:
 I don't think ImportC is that much of a game changer (you can 
 already make C bindings with quite a small effort, and there 
 are tools to get you 90% there), but a broken/not working 
 ImportC will be a huge drawback to the language, so it's 
 important to get it right.
The advantage I though of when I suggested something similar many years ago was that it would enable inlining of C functions, but since then LLVM has gotten whole program optimization over the IR, so now the advantage is more limited. Maybe there are some metaprogramming advantages, but I cannot think of any.
Nov 12 2021
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 12 November 2021 at 08:12:22 UTC, Ola Fosheim Grøstad 
wrote:
 Maybe there are some metaprogramming advantages, but I cannot 
 think of any.
Well, one advantage might be that it could be easier to do escape analysis of C code. Not really sure if there is a difference compared to doing it over the IR, though.
Nov 12 2021
prev sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 9 November 2021 at 11:45:28 UTC, rempas wrote:
 ```
 toml.c(39): Error: cannot implicitly convert expression 
 `malloc` of type `extern (C) void*(ulong __size)` to `extern 
 (C) void* function(ulong)`
 toml.c(40): Error: cannot implicitly convert expression `free` 
 of type `extern (C) void(void* __ptr)` to `extern (C) void 
 function(void*)`
 ```
What's happening here is that dmd seems to see `free` as function rather than a pointer to a function. changing `static void* (*ppmalloc)(size_t) = malloc;` to `static void* (*ppmalloc)(size_t) = &malloc;` may solve your issue.
Nov 09 2021
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/9/21 2:34 PM, Stefan Koch wrote:
 On Tuesday, 9 November 2021 at 11:45:28 UTC, rempas wrote:
 ```
 toml.c(39): Error: cannot implicitly convert expression `malloc` of 
 type `extern (C) void*(ulong __size)` to `extern (C) void* 
 function(ulong)`
 toml.c(40): Error: cannot implicitly convert expression `free` of type 
 `extern (C) void(void* __ptr)` to `extern (C) void function(void*)`
 ```
What's happening here is that dmd seems to see `free` as function rather than a pointer to a function. changing `static void* (*ppmalloc)(size_t) = malloc;` to `static void* (*ppmalloc)(size_t) = &malloc;` may solve your issue.
No, the original is valid C, you don't need the address operator. It's telling that in ldc2 1.28.0, with the new importC feature, it builds fine. It also builds fine with gcc. -Steve
Nov 09 2021
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 9 November 2021 at 19:53:48 UTC, Steven Schveighoffer 
wrote:
 On 11/9/21 2:34 PM, Stefan Koch wrote:
 On Tuesday, 9 November 2021 at 11:45:28 UTC, rempas wrote:
 [...]
What's happening here is that dmd seems to see `free` as function rather than a pointer to a function. changing `static void* (*ppmalloc)(size_t) = malloc;` to `static void* (*ppmalloc)(size_t) = &malloc;` may solve your issue.
No, the original is valid C, you don't need the address operator. It's telling that in ldc2 1.28.0, with the new importC feature, it builds fine. It also builds fine with gcc. -Steve
Yes it is valid C. It is not valid D though.
Nov 09 2021
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/9/21 3:05 PM, Stefan Koch wrote:

 
 Yes it is valid C.
 It is not valid D though.
 
The file is named `tomld.c` The way importC works is, you pass a .c file to the compiler, and it treats it as C. -Steve
Nov 09 2021
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 9 November 2021 at 21:03:20 UTC, Steven Schveighoffer 
wrote:
 On 11/9/21 3:05 PM, Stefan Koch wrote:

 
 Yes it is valid C.
 It is not valid D though.
 
The file is named `tomld.c` The way importC works is, you pass a .c file to the compiler, and it treats it as C. -Steve
It rather tries to interpret the C code as D code. It's not a full C compiler rather it's a shim in front of the D frontend. Therefore bugs like the above can happen if the compiler wasn't aware that the function identifier was to be interpreted in "C context"
Nov 09 2021
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/9/21 5:19 PM, Stefan Koch wrote:
 On Tuesday, 9 November 2021 at 21:03:20 UTC, Steven Schveighoffer wrote:
 On 11/9/21 3:05 PM, Stefan Koch wrote:

 Yes it is valid C.
 It is not valid D though.
The file is named `tomld.c` The way importC works is, you pass a .c file to the compiler, and it treats it as C.
It rather tries to interpret the C code as D code. It's not a full C compiler rather it's a shim in front of the D frontend. Therefore bugs like the above can happen if the compiler wasn't aware that the function identifier was to be interpreted in "C context"
I'm not sure where this conversation is going. ImportC is supposed to compile C files. Any case where it doesn't compile C files (at least standards-conforming ones) is a bug. -Steve
Nov 09 2021
prev sibling parent reply rempas <rempas tutanota.com> writes:
On Tuesday, 9 November 2021 at 22:19:37 UTC, Stefan Koch wrote:
 It rather tries to interpret the C code as D code.
 It's not a full C compiler rather it's a shim in front of the D 
 frontend.
 Therefore bugs like the above can happen if the compiler wasn't 
 aware that the function identifier was to be interpreted in "C 
 context"
I also think that Stefan is right here. If we check the spec page for [ImportC](https://dlang.org/spec/importc.html), in the 2nd note, first sentence, it says: "ImportC is a C compiler embedded into the D implementation". To me that seems that it is a full C compiler that treats the syntax as C and creates files that can be linked with D.
Nov 09 2021
parent rempas <rempas tutanota.com> writes:
On Wednesday, 10 November 2021 at 06:38:58 UTC, rempas wrote:
 On Tuesday, 9 November 2021 at 22:19:37 UTC, Stefan Koch wrote:
 It rather tries to interpret the C code as D code.
 It's not a full C compiler rather it's a shim in front of the 
 D frontend.
 Therefore bugs like the above can happen if the compiler 
 wasn't aware that the function identifier was to be 
 interpreted in "C context"
I also think that Stefan is right here. If we check the spec page for [ImportC](https://dlang.org/spec/importc.html), in the 2nd note, first sentence, it says: "ImportC is a C compiler embedded into the D implementation". To me that seems that it is a full C compiler that treats the syntax as C and creates files that can be linked with D.
*I also think that "STEVEN" is right. Sorry, mistakes happen...
Nov 09 2021
prev sibling parent reply rempas <rempas tutanota.com> writes:
On Tuesday, 9 November 2021 at 19:34:44 UTC, Stefan Koch wrote:
 What's happening here is that dmd seems to see `free` as 
 function rather than a pointer to a function.
 changing `static void* (*ppmalloc)(size_t) = malloc;`
 to `static void* (*ppmalloc)(size_t) = &malloc;`

 may solve your issue.
Thanks for the answer but this seems to create even more bugs
Nov 09 2021
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/10/21 1:31 AM, rempas wrote:
 On Tuesday, 9 November 2021 at 19:34:44 UTC, Stefan Koch wrote:
 What's happening here is that dmd seems to see `free` as function 
 rather than a pointer to a function.
 changing `static void* (*ppmalloc)(size_t) = malloc;`
 to `static void* (*ppmalloc)(size_t) = &malloc;`

 may solve your issue.
Thanks for the answer but this seems to create even more bugs
It shouldn't. Perhaps you mean that you get more errors if you fix that situation? A compiler typically has phases where it can error out. This means that it might not get to further errors (or further errors are happening because of prior errors). It doesn't mean the later errors aren't there, it's just that the compiler gives up before finding them. -Steve
Nov 10 2021
parent rempas <rempas tutanota.com> writes:
On Wednesday, 10 November 2021 at 15:06:26 UTC, Steven 
Schveighoffer wrote:
 It shouldn't.

 Perhaps you mean that you get more errors if you fix that 
 situation? A compiler typically has phases where it can error 
 out. This means that it might not get to further errors (or 
 further errors are happening because of prior errors). It 
 doesn't mean the later errors aren't there, it's just that the 
 compiler gives up before finding them.

 -Steve
Yes, this is exactly what I mean!
Nov 10 2021