www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - callback parameter order question

reply "gedaiu" <szabobogdan yahoo.com> writes:
Hi,

I try to create a D interface to GNU Libmicrohttpd because i 
could not find any, and while i was implementing a demo webserver 
i've noticed that the     MHD_AccessHandlerCallback in D is 
triggered with the parameters in the reverse order.

This is in c:

struct MHD_Daemon *
MHD_start_daemon (unsigned int flags,
		  uint16_t port,
		  MHD_AcceptPolicyCallback apc, void *apc_cls,
		  MHD_AccessHandlerCallback dh, void *dh_cls,
		  ...);

typedef int
   (*MHD_AccessHandlerCallback) (void *cls,
                                 struct MHD_Connection * 
connection,
                                 const char *url,
                                 const char *method,
                                 const char *version,
                                 const char *upload_data,
                                 size_t *upload_data_size,
                                 void **con_cls);



and to work in D I had to this:

alias int function(void **con_cls,
size_t *upload_data_size,
const char *upload_data,
const char *ver,
const char *method,
const char *url,
MHD_Connection* connection,
void* cls) MHD_AccessHandlerCallback;

extern (C) {
     .....
MHD_Daemon *MHD_start_daemon(uint flags, uint port, 
MHD_AcceptPolicyCallback apc, void *apc_cls, 
MHD_AccessHandlerCallback dh, void *dh_cls,...);

....
}
	
Can anyone help me to understand this?

Thanks,
Bogdan
May 11 2013
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/11/13, gedaiu <szabobogdan yahoo.com> wrote:
 alias int function(void **con_cls,
 size_t *upload_data_size,
 const char *upload_data,
 const char *ver,
 const char *method,
 const char *url,
 MHD_Connection* connection,
 void* cls) MHD_AccessHandlerCallback;
Add extern(C) to the alias: alias extern(C) int function(void **con_cls, ...) MHD_AccessHandlerCallback;
May 11 2013
parent reply "gedaiu" <szabobogdan yahoo.com> writes:
On Saturday, 11 May 2013 at 09:39:42 UTC, Andrej Mitrovic wrote:
 On 5/11/13, gedaiu <szabobogdan yahoo.com> wrote:
 alias int function(void **con_cls,
 size_t *upload_data_size,
 const char *upload_data,
 const char *ver,
 const char *method,
 const char *url,
 MHD_Connection* connection,
 void* cls) MHD_AccessHandlerCallback;
Add extern(C) to the alias: alias extern(C) int function(void **con_cls, ...) MHD_AccessHandlerCallback;
if i do that, i get this error src/import/server.d(128): Error: function gnu.microhttpd.MHD_start_daemon (uint flags, uint port, extern (C) int function(void* cls, const(sockaddr*) addr, uint addrlen) apc, void* apc_cls, extern (C) int function(void* cls, MHD_Connection* connection, const(char*) url, const(char*) method, const(char*) ver, const(char*) upload_data, ulong* upload_data_size, void** con_cls) dh, void* dh_cls, ...) is not callable using argument types (MHD_FLAG,int,typeof(null),typeof(null),int function(void* cls, MHD_Connection* connection, const(char*) url, const(char*) method, const(char*) ver, const(char*) upload_data, ulong* upload_data_size, void** ptr) system,typeof(null),MHD_OPTION) src/import/server.d(128): Error: cannot implicitly convert expression (ahc_echo) of type int function(void* cls, MHD_Connection* connection, const(char*) url, const(char*) method, const(char*) ver, const(char*) upload_data, ulong* upload_data_size, void** ptr) system to extern (C) int function(void* cls, MHD_Connection* connection, const(char*) url, const(char*) method, const(char*) ver, const(char*) upload_data, ulong* upload_data_size, void** con_cls)
May 11 2013
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/11/13, gedaiu <szabobogdan yahoo.com> wrote:
 if i do that, i get this error
I don't know what "ahc_echo" is, but I imagine you'll have to make it an extern(C) function.
May 11 2013
parent reply "gedaiu" <szabobogdan yahoo.com> writes:
On Saturday, 11 May 2013 at 10:04:54 UTC, Andrej Mitrovic wrote:
 On 5/11/13, gedaiu <szabobogdan yahoo.com> wrote:
 if i do that, i get this error
I don't know what "ahc_echo" is, but I imagine you'll have to make it an extern(C) function.
Hi, i have this code, and i don't think i can add extern(C) there void start() { auto ahc_echo = function(void* cls, MHD_Connection* connection, const char *url, const char *method, const char *ver, const char *upload_data, size_t *upload_data_size, void **ptr) { ... }; d = MHD_start_daemon(MHD_FLAG.MHD_USE_THREAD_PER_CONNECTION, 8080, null, null, ahc_echo, null, MHD_OPTION.MHD_OPTION_END); } and if i create a function like this: extern(C) int ahc_echo(void* cls, MHD_Connection* connection, const char *url, const char *method, const char *ver, const char *upload_data, size_t *upload_data_size, void **ptr) { .... }; i get this error: Error: function cmsutils.CMServer.ahc_echo (void* cls, MHD_Connection* connection, const(char*) url, const(char*) method, const(char*) ver, const(char*) upload_data, ulong* upload_data_size, void** ptr) is not callable using argument types () Error: expected 8 function arguments, not 0
May 11 2013
next sibling parent reply "evilrat" <evilrat666 gmail.com> writes:
On Saturday, 11 May 2013 at 10:44:01 UTC, gedaiu wrote:
 On Saturday, 11 May 2013 at 10:04:54 UTC, Andrej Mitrovic wrote:
 On 5/11/13, gedaiu <szabobogdan yahoo.com> wrote:
 if i do that, i get this error
I don't know what "ahc_echo" is, but I imagine you'll have to make it an extern(C) function.
Hi, i have this code, and i don't think i can add extern(C) there void start() { auto ahc_echo = function(void* cls, MHD_Connection* connection, const char *url, const char *method, const char *ver, const char *upload_data, size_t *upload_data_size, void **ptr) { ... }; d = MHD_start_daemon(MHD_FLAG.MHD_USE_THREAD_PER_CONNECTION, 8080, null, null, ahc_echo, null, MHD_OPTION.MHD_OPTION_END); } and if i create a function like this: extern(C) int ahc_echo(void* cls, MHD_Connection* connection, const char *url, const char *method, const char *ver, const char *upload_data, size_t *upload_data_size, void **ptr) { .... }; i get this error: Error: function cmsutils.CMServer.ahc_echo (void* cls, MHD_Connection* connection, const(char*) url, const(char*) method, const(char*) ver, const(char*) upload_data, ulong* upload_data_size, void** ptr) is not callable using argument types () Error: expected 8 function arguments, not 0
looks like you are trying to pass func as parameter in this func, but you forgot to take its address d = MHD_start_daemon(MHD_FLAG.MHD_USE_THREAD_PER_CONNECTION, 8080, null, null, &ahc_echo, // <-- here null, MHD_OPTION.MHD_OPTION_END);
May 11 2013
parent reply "gedaiu" <szabobogdan yahoo.com> writes:
On Saturday, 11 May 2013 at 11:28:10 UTC, evilrat wrote:
 On Saturday, 11 May 2013 at 10:44:01 UTC, gedaiu wrote:
 On Saturday, 11 May 2013 at 10:04:54 UTC, Andrej Mitrovic 
 wrote:
 On 5/11/13, gedaiu <szabobogdan yahoo.com> wrote:
 if i do that, i get this error
I don't know what "ahc_echo" is, but I imagine you'll have to make it an extern(C) function.
Hi, i have this code, and i don't think i can add extern(C) there void start() { auto ahc_echo = function(void* cls, MHD_Connection* connection, const char *url, const char *method, const char *ver, const char *upload_data, size_t *upload_data_size, void **ptr) { ... }; d = MHD_start_daemon(MHD_FLAG.MHD_USE_THREAD_PER_CONNECTION, 8080, null, null, ahc_echo, null, MHD_OPTION.MHD_OPTION_END); } and if i create a function like this: extern(C) int ahc_echo(void* cls, MHD_Connection* connection, const char *url, const char *method, const char *ver, const char *upload_data, size_t *upload_data_size, void **ptr) { .... }; i get this error: Error: function cmsutils.CMServer.ahc_echo (void* cls, MHD_Connection* connection, const(char*) url, const(char*) method, const(char*) ver, const(char*) upload_data, ulong* upload_data_size, void** ptr) is not callable using argument types () Error: expected 8 function arguments, not 0
looks like you are trying to pass func as parameter in this func, but you forgot to take its address d = MHD_start_daemon(MHD_FLAG.MHD_USE_THREAD_PER_CONNECTION, 8080, null, null, &ahc_echo, // <-- here null, MHD_OPTION.MHD_OPTION_END);
yeah... what a shameful mistake.. i vave a new tricky question... how i can provide a class method instead a simple function as callback?
May 11 2013
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/11/2013 10:34 AM, gedaiu wrote:

 how i can provide a class method instead a simple function as
 callback?
Can you describe a little bit more? Where will the object that the member function will be called on come from? Do you want to use always the same object that you already have up front, or do you want to create a new object when the member function needs to be called? In any case, you will have to use a delegate. Ali
May 11 2013
prev sibling parent "evilrat" <evilrat666 gmail.com> writes:
On Saturday, 11 May 2013 at 17:34:53 UTC, gedaiu wrote:
 yeah... what a shameful mistake.. i vave a new tricky 
 question... how i can provide a class method instead a simple 
 function as callback?
with D code use delegates as Ali commented, it's simple. with C code use static method and pass instance pointer as callback target, something like this --------------- // C function alias extern(C) function(void*) callbackfunc; extern(C) setCallback(callbackfunc cb, void* userptr); class Handler { static extern(C) callback(void* instance) { if ( auto self = cast(Handler) instance ) self.onCallback(); } void onCallback() { // ... // your code here // ... } } void setCAPI_callback(Handler hnd) { setCallback(Handler.callback, hnd); // don't remember if needed to cast hnd to void } however this would require C API which has userptr argument in callbacks(hopefully most libs i've seen has this)
May 11 2013
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/11/13, gedaiu <szabobogdan yahoo.com> wrote:
 i have this code, and i don't think i can add extern(C) there
That's a problem with the parser. Instead of auto use the actual function type: alias extern(C) int function(void **con_cls, size_t *upload_data_size, const char *upload_data, const char *ver, const char *method, const char *url, MHD_Connection* connection, void* cls) MHD_AccessHandlerCallback; ... MHD_AccessHandlerCallback ahc_echo = function(void* cls, MHD_Connection* connection, const char *url, const char *method, const char *ver, const char *upload_data, size_t *upload_data_size, void **ptr) { ... };
May 11 2013