Thread overview
Question about function aliases
Dec 11, 2013
Gary Willoughby
Dec 12, 2013
dnewbie
Dec 12, 2013
Gary Willoughby
Dec 12, 2013
bearophile
Dec 12, 2013
FreeSlave
Dec 17, 2013
Gary Willoughby
December 11, 2013
For example i have some C code like this:

typedef void (Tcl_InterpDeleteProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp));

void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc* proc, ClientData clientData);


I intend on converted this to D thus:

alias void function(ClientData clientData, Tcl_Interp* interp) Tcl_InterpDeleteProc;

void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc* proc, ClientData clientData);

Is it correct keeping the * with the Tcl_InterpDeleteProc parameter or do i remove it? Is the alias above a function pointer?

To call this function can i use a function literal for the Tcl_InterpDeleteProc parameter? or do i need to pass an address of the function?
December 12, 2013
On Wednesday, 11 December 2013 at 23:42:44 UTC, Gary Willoughby wrote:
> For example i have some C code like this:
>
> typedef void (Tcl_InterpDeleteProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp));
>
> void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc* proc, ClientData clientData);
>
>
> I intend on converted this to D thus:
>
> alias void function(ClientData clientData, Tcl_Interp* interp) Tcl_InterpDeleteProc;
>
> void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc* proc, ClientData clientData);
>
> Is it correct keeping the * with the Tcl_InterpDeleteProc parameter or do i remove it? Is the alias above a function pointer?
>
> To call this function can i use a function literal for the Tcl_InterpDeleteProc parameter? or do i need to pass an address of the function?

It's a function pointer.
Test:

import std.stdio;
alias extern(C) void function(void*) Callback;

void Call(Callback c)
{
    c(c);
}

extern(C) void callback(void* v)
{
    writefln("v: %04X", v);
}
	
void main()
{
    Callback c = &callback;
    Call(c);	
    writefln("c: %04X", c);
}
December 12, 2013
On Thursday, 12 December 2013 at 00:51:56 UTC, dnewbie wrote:
> On Wednesday, 11 December 2013 at 23:42:44 UTC, Gary Willoughby wrote:
>> For example i have some C code like this:
>>
>> typedef void (Tcl_InterpDeleteProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp));
>>
>> void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc* proc, ClientData clientData);
>>
>>
>> I intend on converted this to D thus:
>>
>> alias void function(ClientData clientData, Tcl_Interp* interp) Tcl_InterpDeleteProc;
>>
>> void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc* proc, ClientData clientData);
>>
>> Is it correct keeping the * with the Tcl_InterpDeleteProc parameter or do i remove it? Is the alias above a function pointer?
>>
>> To call this function can i use a function literal for the Tcl_InterpDeleteProc parameter? or do i need to pass an address of the function?
>
> It's a function pointer.
> Test:
>
> import std.stdio;
> alias extern(C) void function(void*) Callback;
>
> void Call(Callback c)
> {
>     c(c);
> }
>
> extern(C) void callback(void* v)
> {
>     writefln("v: %04X", v);
> }
> 	
> void main()
> {
>     Callback c = &callback;
>     Call(c);	
>     writefln("c: %04X", c);
> }

So i guess i need to remove the * after the Tcl_InterpDeleteProc parameter from the C declaration when porting it?

Using the * my tests show an error which i guess is caused by the declaration expecting a pointer to a function pointer.

Here is my test:

import std.stdio;

// Function pointer type.
alias void function(string text, int level) Tcl_InterpDeleteProc;

// A function that uses the function pointer type for a parameter.
void test(Tcl_InterpDeleteProc func) // <-- no *
{
	(*func)("Hello", 100);
}

// A callback that going to be used as the parameter.
void callback(string text, int level)
{
	writefln("text : %s", text);
	writefln("level: %d", level);
}

// test.
void main(string[] args)
{
	// Use address of function.
	test(&callback);

	// Function literal passed as pointer.
	test(function(string text, int level){
		writefln("text : %s", text);
		writefln("level: %d", level);
	});
}

After testing i've decided on the following code for the port. Would you agree this is correct?

alias void function(ClientData clientData, Tcl_Interp* interp)  Tcl_InterpDeleteProc;

extern (C) void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc proc, ClientData clientData);
December 12, 2013
Gary Willoughby:

> alias void function(ClientData clientData, Tcl_Interp* interp)  Tcl_InterpDeleteProc;
>
> extern (C) void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc proc, ClientData clientData);

With recent D compilers I prefer the alias with "=" and a more
aligned colums formatting of the arguments when they don't fit
well in a line:


alias Tcl_InterpDeleteProc = void function(ClientData clientData,
Tcl_Interp* interp);

extern(C) void Tcl_CallWhenDeleted(Tcl_Interp* interp,
                                    Tcl_InterpDeleteProc proc,
                                    ClientData clientData);

Also, can't you add some "const" in those arguments? Is your C
function pure? It should be nothrow.

Bye,
bearophile
December 12, 2013
On Thursday, 12 December 2013 at 11:11:55 UTC, bearophile wrote:
> Gary Willoughby:
>
>> alias void function(ClientData clientData, Tcl_Interp* interp)
>>  Tcl_InterpDeleteProc;
>>
>> extern (C) void Tcl_CallWhenDeleted(Tcl_Interp* interp, Tcl_InterpDeleteProc proc, ClientData clientData);
>
> With recent D compilers I prefer the alias with "=" and a more
> aligned colums formatting of the arguments when they don't fit
> well in a line:
>
>
> alias Tcl_InterpDeleteProc = void function(ClientData clientData,
> Tcl_Interp* interp);
>
> extern(C) void Tcl_CallWhenDeleted(Tcl_Interp* interp,
>                                     Tcl_InterpDeleteProc proc,
>                                     ClientData clientData);
>
> Also, can't you add some "const" in those arguments? Is your C
> function pure? It should be nothrow.
>
> Bye,
> bearophile

I guess alias also should include extern(C) declaration i.e. the right way is
alias Tcl_InterpDeleteProc = extern(C) void function(ClientData clientData, Tcl_Interp* interp) nothrow;

So your callback on D side must have C-linkage too.
Lack of extern(C) in alias probably will not cause problem on Linux, but in my experience, Windows requires it otherwise you will get seg fault.
December 17, 2013
On Thursday, 12 December 2013 at 11:39:56 UTC, FreeSlave wrote:
> I guess alias also should include extern(C) declaration i.e. the right way is
> alias Tcl_InterpDeleteProc = extern(C) void function(ClientData clientData, Tcl_Interp* interp) nothrow;

Unfortunately that syntax doesn't compile. The alternative does however.