From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,86f62fb0f98ad93e X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news2.google.com!npeer01.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!nx02.iad01.newshosting.com!newshosting.com!novia!news-xxxfer.readnews.com!transit4.readnews.com!news-out.readnews.com!transit3.readnews.com!teleglobe.net!newsgate.cuhk.edu.hk!news.netfront.net!not-for-mail From: Jeffrey Carter Newsgroups: comp.lang.ada Subject: Re: Passing Ada Proc as a C Function Pointer Date: Wed, 04 Aug 2010 11:46:56 -0700 Organization: Netfront http://www.netfront.net/ Message-ID: References: NNTP-Posting-Host: 75.211.96.51 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: adenine.netfront.net 1280947618 77553 75.211.96.51 (4 Aug 2010 18:46:58 GMT) X-Complaints-To: news@netfront.net NNTP-Posting-Date: Wed, 4 Aug 2010 18:46:58 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.11) Gecko/20100713 Thunderbird/3.0.6 In-Reply-To: Xref: g2news1.google.com comp.lang.ada:12858 Date: 2010-08-04T11:46:56-07:00 List-Id: On 08/04/2010 09:40 AM, Warren wrote: > I some types defined as: > > type Thread_Context is private; > type Stack_Area is new String; > type Thread_Proc is access procedure; > > and an Ada API function: > > procedure Thread_Start(Context : out Thread_Context; Proc : > Thread_Proc; Stack : out Stack_Area) is > type C_Func_Ptr is access procedure; > pragma Convention(Convention => C, Entity => C_Func_Ptr); > > procedure avr_thread_start(Context : System.Address; > Proc : C_Func_Ptr; > Stack : System.Address; > Size : Unsigned_16); > pragma import(C,avr_thread_start,"avr_thread_start"); > > Func : C_Func_Ptr := Proc.all'Access; > begin > > > avr_thread_start(Context'Address,Func,Stack(Stack'First)'Address,Stack'Length); > > end Thread_Start; > > Because this part of the Ada code is not working, I'm suspicious that > the passed function pointer is incorrect (I have an all-C thread > example > working). > > Is it vital that the Thread_Proc procedure also be declared as > > pragma import(C,Proc) ? > > I'd prefer not to, if possible. > > There are no arguments passed-- I only need to launch the passed > Ada procedure from the C side (in a thread). > > The avr_thread_start C routine is declared as: > > void avr_thread_start( > avr_thread_context* context, > void (*fn)(void), > uint8_t* stack, > uint16_t stack_size > ); I'm presuming that you want Ada to call Thread_Start and not need to take special steps because Thread_Start calls some C. In that case, you should ignore most of what Kazakov said: The Ada-side declarations should not reflect the implementation. The 1st step is to translate the C side into something meaningful. "uint8_t*" can mean a host of things: * in uint8_t (uncommon) * in out uint8_t * out uint8_t * in array_of_uint8_t * in out array_of_uint8_t * out array_of_uint8_t I'll presume from your use of "out" that "context" and "stack" are "out", and from your use of "new String" that "stack" is an array. Next, you need to use convention-C types for your C parameters. There is no guarantee that System.Address corresponds to a C pointer; if you're at all interested in compiler portability, you won't use it. You also won't use "new String" for the "uint8_t*" parameter. So I'd do something like (untested): procedure Thread_Start(Context : out Thread_Context; Proc : in Thread_Proc; Stack : out Stack_Area) is type C_Context is ...; -- Something C-compatible that corresponds to the C -- definition of avr_thread_context, using only -- convention-C components. pragma Convention (C, C_Context); procedure Local_Proc is -- null; begin -- Local_Proc Proc.all; end Local_Proc; pragma Convention (C, Local_Proc); subtype Stack_String is Stack_Area (Stack'range); type U8 is mod 2 ** 8; pragma Convention (C, U8); type U8_List is array (Stack'range) of U8; pragma Convention (C, U8_List); type U16 is mod 2 ** 16; pragma Convention (C, U16); procedure AVR_Thread_Start (Context : out C_Context; Proc : access procedure; Stack : out U8_List; Size : in U16); pragma Import (C, AVR_Thread_Start, "avr_thread_start"); Local_Context : C_Context; Local_Stack : U8_List; -- function To_Thread_Context (From : C_Context) return Thread_Context; -- -- function To_Stack_Area (From : U8_List) return Stack_String; -- Implementations left as exercises for the reader. begin -- Thread_Start AVR_Thread_Start (Context => Local_Context, Proc => Local_Proc'access, Stack => Local_Stack, Size => Local_Stack'Length); Context := To_Thread_Context (Local_Context); Stack := To_Stack_Area (Local_Stack); end Thread_Start; Ada will pass Stack as a "U8*" pointing to the first component and Context as an appropriate pointer; see ARM B.3. Local_Context and Local_Stack give us convention-C objects to pass; Local_Proc a convention-C procedure that C may call. I presume Thread_Context is not opaque and its contents are accessed on the Ada side. Otherwise you may be able to get away with a convention-C pointer to Thread_Context. Are Context and Stack really needed outside Thread_Start? -- Jeff Carter "Ah, go away or I'll kill ya." Never Give a Sucker an Even Break 100 --- news://freenews.netfront.net/ - complaints: news@netfront.net ---