Thread overview
How to call a C function from D that takes a FILE * as an argument?
Jul 04, 2018
Joe
Jul 04, 2018
Seb
Jul 04, 2018
Joe
Jul 04, 2018
Seb
Jul 04, 2018
Joe
Jul 04, 2018
Adam D. Ruppe
Jul 04, 2018
WebFreak001
July 04, 2018
The subject basically says it all. The C function uses the argument to call fprintf and also passes it to other functions where it's used to call fileno, fprintf or putc.
July 04, 2018
On Wednesday, 4 July 2018 at 01:06:36 UTC, Joe wrote:
> The subject basically says it all. The C function uses the argument to call fprintf and also passes it to other functions where it's used to call fileno, fprintf or putc.

Like you would with C's fprintf (https://dlang.org/phobos/core_stdc_stdio.html#.fprintf).
For example, this is a valid D program:

---
void main(string[] args)
{
    import core.stdc.stdio;
    FILE* pFile;
    int n;
    char[100] name;

    pFile = fopen ("myfile.txt","w"); // string literals are zero-terminated
    for (n=0 ; n<3 ; n++)
    {
        puts("please, enter a name: ");
        gets(name.ptr);
        fprintf pFile, "Name %d [%-10.10s]\n",n+1,name.ptr);
    }
    fclose(pFile);
}
---

(example from http://www.cplusplus.com/reference/cstdio/fprintf)

So just add the declaration to your D file:

---
extern(C) void myCfunction(FILE* stream);
---

and as long as you link your program into the D binary, you should be good to go.
For larger C bases, tools like dstep or dpp can help translating C/C++ header files to D.
July 04, 2018
On Wednesday, 4 July 2018 at 01:58:15 UTC, Seb wrote:
> So just add the declaration to your D file:
>
> ---
> extern(C) void myCfunction(FILE* stream);
> ---

I do have a similar declaration in D.  It appears the problem is that the C program I'm trying to convert passes stdout as the argument and the D compiler complains somewhat like the following:


Error: function foo.main.myCfunction (shared(_IO_FILE)* stream) is not callable using argument types (File)

So I guess the question is what to pass instead of stdout.
July 04, 2018
On Wednesday, 4 July 2018 at 02:08:11 UTC, Joe wrote:
> On Wednesday, 4 July 2018 at 01:58:15 UTC, Seb wrote:
>> So just add the declaration to your D file:
>>
>> ---
>> extern(C) void myCfunction(FILE* stream);
>> ---
>
> I do have a similar declaration in D.  It appears the problem is that the C program I'm trying to convert passes stdout as the argument and the D compiler complains somewhat like the following:
>
>
> Error: function foo.main.myCfunction (shared(_IO_FILE)* stream) is not callable using argument types (File)
>
> So I guess the question is what to pass instead of stdout.

Hmm, calling e.g. fprintf with stdout should just work:

---
void main()
{
    import core.stdc.stdio;
    fprintf(stdout, "Hello %s", "world".ptr);
}
---

Could you maybe provide your whole code?
July 04, 2018
On Wednesday, 4 July 2018 at 02:16:00 UTC, Seb wrote:
> Hmm, calling e.g. fprintf with stdout should just work:
>
> ---
> void main()
> {
>     import core.stdc.stdio;
>     fprintf(stdout, "Hello %s", "world".ptr);
> }
> ---
>
> Could you maybe provide your whole code?

This short test program shows the error:

---
import std.stdio;


void main()
{
    extern (C) void list(FILE *fd);
    list(stdout);
}
---

Now I fixed this by changing the import to core.stdc.stdio. I guess the problem is if you import std.stdio (which brings in the other one), there are two slightly incompatible stdout's and the D takes precedence.
July 04, 2018
On Wednesday, 4 July 2018 at 02:54:47 UTC, Joe wrote:
> Now I fixed this by changing the import to core.stdc.stdio. I guess the problem is if you import std.stdio (which brings in the other one), there are two slightly incompatible stdout's and the D takes precedence.

If you import both modules (or even I think if just the D std.stdio, since it publicly imports the other), you can specify the C one by using its full name:

core.stdc.stdio.stdout

where you use it. of course you can also alias it to something shorter.
July 04, 2018
On Wednesday, 4 July 2018 at 02:54:47 UTC, Joe wrote:
> On Wednesday, 4 July 2018 at 02:16:00 UTC, Seb wrote:
>> Hmm, calling e.g. fprintf with stdout should just work:
>>
>> ---
>> void main()
>> {
>>     import core.stdc.stdio;
>>     fprintf(stdout, "Hello %s", "world".ptr);
>> }
>> ---
>>
>> Could you maybe provide your whole code?
>
> This short test program shows the error:
>
> ---
> import std.stdio;
>
>
> void main()
> {
>     extern (C) void list(FILE *fd);
>     list(stdout);
> }
> ---
>
> Now I fixed this by changing the import to core.stdc.stdio. I guess the problem is if you import std.stdio (which brings in the other one), there are two slightly incompatible stdout's and the D takes precedence.

`stdout.getFP` (stdout is of the D std.stdio.File struct type and with getFP you get the underlying FILE*)