1. undefine_c_func (was: memory profiling)

Thank you, Rob, for your response.  I'll see if I have the latest version of 
Matt's ODBC lib first, since he's already fixed a few leaks.  Then I'll try
recompiling the interpreter if the problem gets too bad.

Now for the next question (unrelated):
I'm currently in the process of updating EuGTK.
GTK 2.6 has a procedure that allows for a variable number of arguments,
similar to the way printf does.  define_c_proc does not allow for this.  My
next thought was to simply define the procedure with the correct number of
arguments each time it's needed.  Except, without a matching undefine to
free the memory, we introduce a leak into the library.  If the routine is only
called once or twice, that's not a big problem.  But if the routine is needed
a few thousand times, that's an issue.  There is the option of completely
rewriting the function in Euphoria terms instead of using the API call, but
I'd prefer a simpler answer if it exists.

Thoughts?

Michael Sabal

new topic     » topic index » view message » categorize

2. Re: undefine_c_func (was: memory profiling)

Michael J. Sabal wrote:
[snip]
> Now for the next question (unrelated):
> I'm currently in the process of updating EuGTK.
> GTK 2.6 has a procedure that allows for a variable number of arguments,
> similar to the way printf does.  define_c_proc does not allow for this.  My
> next thought was to simply define the procedure with the correct number of
> arguments each time it's needed.  Except, without a matching undefine to
> free the memory, we introduce a leak into the library.  If the routine is only
> called once or twice, that's not a big problem.  But if the routine is needed
> a few thousand times, that's an issue.  There is the option of completely
> rewriting the function in Euphoria terms instead of using the API call, but
> I'd prefer a simpler answer if it exists.
> 
> Thoughts?
> 
> Michael Sabal

Hi Michael,

I had the same issue with Euallegro.
I made the Euphoria version pass a sequence of parameters 
(the same way the builtin Euphoria printf works) and in my wrapper routine I 
call sprintf() and pass the results of this to the C routines.


E.g:

C definition:

void allegro_message(const char *text_format, ...);


Eu routine:

constant my_allegro_message = link_proc(AllegroLib, "allegro_message",
{C_POINTER})
global procedure allegro_message(sequence msg, sequence parms)
   atom msg_ptr
   sequence tmp

   tmp = sprintf(msg, parms)
   msg_ptr = allocate_string(tmp)
   c_proc(my_allegro_message, {msg_ptr})
   free(msg_ptr)
end procedure



Usage:

integer dummy1, dummy2
dummy1=123
dummy2=456
allegro_message( "This is a Test %d %d", {dummy1, dummy2})



Regards,

Ray Smith
http://RaymondSmith.com

new topic     » goto parent     » topic index » view message » categorize

3. Re: undefine_c_func (was: memory profiling)

Try passing the parameters as an array of INTs

IIRC, varg uses the first element for argc, the remaining elements of the array
are argv.

I use that technique in mambo for dll function prototypes so I only need to have
one proto instead of one for every number of args passed.

I'll see if I can find the code I use in mambo.

Chris Bensler
~ The difference between ordinary and extraordinary is that little extra ~
http://empire.iwireweb.com - Empire for Euphoria

new topic     » goto parent     » topic index » view message » categorize

4. Re: undefine_c_func (was: memory profiling)

On Sun, 19 Nov 2006 15:25:53 -0800, "Michael J. Sabal"
<guest at RapidEuphoria.com> wrote:

>GTK 2.6 has a procedure that allows for a variable number of arguments,
>similar to the way printf does.  define_c_proc does not allow for this.  My
>next thought was to simply define the procedure with the correct number of
>arguments each time it's needed.  Except, without a matching undefine to
>free the memory, we introduce a leak into the library.
Why not just store results from define_c_proc in a sequence?
Eg:
object xXxxx
       xXxxx = 0

global procedure Eu_xXxxx(sequence params)
integer l
atom p
    l = length(params)
    if atom(xXxxx) then
        xXxxx=repeat(0,l)
    elsif l>length(xXxxx) then
        xXxxx&=repeat(0,l-length(xXxxx))
    end if
    p = xXxxx[l]
    if p=0 then
        p = define_c_proc(lib,"Xxxx",repeat(C_POINTER,l),C_INT)
        xXxxx[l] = p
    end if
    c_proc(p,params)
end procedure


Regards,
Pete

new topic     » goto parent     » topic index » view message » categorize

5. Re: undefine_c_func (was: memory profiling)

Pete Lomax wrote:
> 
> On Sun, 19 Nov 2006 15:25:53 -0800, "Michael J. Sabal"
> <guest at RapidEuphoria.com> wrote:
> 
> >GTK 2.6 has a procedure that allows for a variable number of arguments,
> >similar to the way printf does.  define_c_proc does not allow for this.  My
> >next thought was to simply define the procedure with the correct number of
> >arguments each time it's needed.  Except, without a matching undefine to
> >free the memory, we introduce a leak into the library.
> Why not just store results from define_c_proc in a sequence?
> Eg:
> }}}
<eucode>
> object xXxxx
>        xXxxx = 0
> 
> global procedure Eu_xXxxx(sequence params)
> integer l
> atom p
>     l = length(params)
>     if atom(xXxxx) then
>         xXxxx=repeat(0,l)
>     elsif l>length(xXxxx) then
>         xXxxx&=repeat(0,l-length(xXxxx))
>     end if
>     p = xXxxx[l]
>     if p=0 then
>         p = define_c_proc(lib,"Xxxx",repeat(C_POINTER,l),C_INT)
>         xXxxx[l] = p
>     end if
>     c_proc(p,params)
> end procedure
> </eucode>
{{{

> 
> Regards,
> Pete

There is no need for these kinds of hacks, variadic functions are fairly simple
to interface with once you know how.
I'm mostly going from memory and a lack of available informaton, but..

All the params are stored as an array of INT's or DOUBLES, depending on the
actual type of the argument. Types are promoted, so char/short -> INT and float
-> DOUBLE

It is the function's responsibility to know what the types of the arguments are
supposed to be and how many.

Eg printf's first argument is a format string which inherently specifies the
types of the variable arguments via the format flags.

Other functions typically will just expect a certain type for a given argument.
Eg, a list of string pointers

All variadic functions in C have to have at least one named argument, the last
of which is the first element of the variadic array. To denote how many args are
passed, 0-terminate the array. Some functions will determine the number of
arguments from one of the arguments (normally a named argument or the first
variadic or implicitly), but it will never hurt to 0-terminate the array.

Here is a code example to give you an idea
(untested/pseudo code, I doubt it will actually work, you will likely need to
experiment a bit as I have not dealt with variadic functions much or in a long
time)

constant xcprintf = define_c_proc(DLL,"printf",{UINT})
procedure cprintf(object format, sequence args)
 atom lpargs,lp
  args = {format} & args
lpargs = allocate(8*(length(args)+1)) -- allocate maximum size.. +1 for NULL
  terminator
  lp = lpargs
  for i = 1 to length(args) do
    if sequence(args[i]) then
      poke4(lp, allocate_string(args[i]))
      lp += 4
    elsif (args[i] < #100000000) and (floor(args[i]) = args[i]) then -- int
      poke4(lp,args[i])
      lp += 4
    else -- float
      poke(atom_to_float64(args[i]))
      lp += 8
    end if
  end for
  c_proc(cprintf,{lpargs})
  lp = lpargs
  for i = 1 to length(args) do
    if sequence(args[i]) then
      free(lp)
      lp += 4
    elsif (args[i] < #100000000) and (floor(args[i]) = args[i]) then -- int
      lp += 4
    else -- float
      lp += 8
    end if
  end for
  free(lpargs)
end procedure


HTH

Chris Bensler
~ The difference between ordinary and extraordinary is that little extra ~
http://empire.iwireweb.com - Empire for Euphoria

new topic     » goto parent     » topic index » view message » categorize

6. Re: undefine_c_func (was: memory profiling)

Chris Bensler wrote:
> 
> Pete Lomax wrote:
> > 
> > On Sun, 19 Nov 2006 15:25:53 -0800, "Michael J. Sabal"
> > <guest at RapidEuphoria.com> wrote:
> > 
> > >GTK 2.6 has a procedure that allows for a variable number of arguments,
> > >similar to the way printf does.  define_c_proc does not allow for this.  My
> > >next thought was to simply define the procedure with the correct number of
> > >arguments each time it's needed.  Except, without a matching undefine to
> > >free the memory, we introduce a leak into the library.
> > Why not just store results from define_c_proc in a sequence?
> > Eg:
> > }}}
<eucode>
> > object xXxxx
> >        xXxxx = 0
> > 
> > global procedure Eu_xXxxx(sequence params)
> > integer l
> > atom p
> >     l = length(params)
> >     if atom(xXxxx) then
> >         xXxxx=repeat(0,l)
> >     elsif l>length(xXxxx) then
> >         xXxxx&=repeat(0,l-length(xXxxx))
> >     end if
> >     p = xXxxx[l]
> >     if p=0 then
> >         p = define_c_proc(lib,"Xxxx",repeat(C_POINTER,l),C_INT)
> >         xXxxx[l] = p
> >     end if
> >     c_proc(p,params)
> > end procedure
> > </eucode>
{{{

> > 
> > Regards,
> > Pete
> 
> There is no need for these kinds of hacks, variadic functions are fairly
> simple
> to interface with once you know how.
> I'm mostly going from memory and a lack of available informaton, but..
> 
> All the params are stored as an array of INT's or DOUBLES, depending on the
> actual
> type of the argument. Types are promoted, so char/short -> INT and float ->
> DOUBLE
> 
> It is the function's responsibility to know what the types of the arguments
> are supposed to be and how many.
> 
> Eg printf's first argument is a format string which inherently specifies the
> types of the variable arguments via the format flags.
> 
> Other functions typically will just expect a certain type for a given
> argument.
> Eg, a list of string pointers
> 
> All variadic functions in C have to have at least one named argument, the last
> of which is the first element of the variadic array. To denote how many args
> are passed, 0-terminate the array. Some functions will determine the number
> of arguments from one of the arguments (normally a named argument or the first
> variadic or implicitly), but it will never hurt to 0-terminate the array.
> 
> Here is a code example to give you an idea
> (untested/pseudo code, I doubt it will actually work, you will likely need to
> experiment a bit as I have not dealt with variadic functions much or in a long
> time)
> 
> }}}
<eucode>
> constant xcprintf = define_c_proc(DLL,"printf",{UINT})
> procedure cprintf(object format, sequence args)
>  atom lpargs,lp
>   args = {format} & args
>   lpargs = allocate(8*(length(args)+1)) -- allocate maximum size.. +1 for NULL
>   terminator
>   lp = lpargs
>   for i = 1 to length(args) do
>     if sequence(args[i]) then
>       poke4(lp, allocate_string(args[i]))
>       lp += 4
>     elsif (args[i] < #100000000) and (floor(args[i]) = args[i]) then -- int
>       poke4(lp,args[i])
>       lp += 4
>     else -- float
>       poke(atom_to_float64(args[i]))
>       lp += 8
>     end if
>   end for
>   c_proc(cprintf,{lpargs})
>   lp = lpargs
>   for i = 1 to length(args) do
>     if sequence(args[i]) then
>       free(lp)
>       lp += 4
>     elsif (args[i] < #100000000) and (floor(args[i]) = args[i]) then -- int
>       lp += 4
>     else -- float
>       lp += 8
>     end if
>   end for
>   free(lpargs)
> end procedure
> </eucode>
{{{

> 
> HTH
> 
> Chris Bensler
> ~ The difference between ordinary and extraordinary is that little extra ~
> <a href="http://empire.iwireweb.com">http://empire.iwireweb.com</a> - Empire
> for Euphoria

Oops, I missed poking the null terminator (not needed for printf anyway)
And I also didn't declare printf as cdecl "+printf" (all variadic functions are
cdecl)

Chris Bensler
~ The difference between ordinary and extraordinary is that little extra ~
http://empire.iwireweb.com - Empire for Euphoria

new topic     » goto parent     » topic index » view message » categorize

7. Re: undefine_c_func (was: memory profiling)

On Mon, 20 Nov 2006 05:32:34 -0800, Chris Bensler
<guest at RapidEuphoria.com> wrote:

>There is no need for these kinds of hacks, 
Oh/Uh?
>variadic functions are fairly simple to interface with once you know how.
>I'm mostly going from memory and a lack of available informaton, but..
OK, I'm listening...
>
>All the params are stored as an array of INT's or DOUBLES, depending on the
>actual type of the argument. Types are promoted, so char/short -> INT and float
>-> DOUBLE
That is not at all what I was taught.[1]
>
>It is the function's responsibility to know what the types of the arguments are
>supposed to be and how many.
Nor that[2]
>
>Eg printf's first argument is a format string which inherently specifies the
>types of the variable arguments via the format flags.
Nor that[3]
>
<snip>
>
>Here is a code example to give you an idea
>(untested/pseudo code, I doubt it will actually work, 
OK, gauntlet down. Make it work. I claim you will not be able to.
I'll accept a reasonable forfeit should you prove me wrong, of 
course /only/ if you can do so with /less/ "hacks" than the wee 
sequence of define_c_proc results I proposed, and keep say
60% of the code you posted?

Regards,
Pete
[1] Far as I know, in most languages (not Eu, of course), parameters
are pushed onto the stack, and the stack is kept machine-word aligned
by default. There's no "array" involved, though they do end up next to
each other by the time the function sees them.
[2] It is NOT a mandate that a (C) function must crash when passed
arguments of the wrong type. Any "responsibility" clearly lies with
the caller, not the callee. 
[3] Clearly printf will print rubbish, and/or ignore excess arguments.
Inherently it has /no/ type checking abilities. Quite how one might
print 0 when you 0-terminate this fictional array is a mystery to me.

new topic     » goto parent     » topic index » view message » categorize

8. Re: undefine_c_func (was: memory profiling)

Chris Bensler wrote:
> 
> Oops, I missed poking the null terminator (not needed for printf anyway)
> And I also didn't declare printf as cdecl "+printf" (all variadic functions
> are cdecl)
> 

I tried running your code with these modifications under 2 scenarios:  
define_c_proc("","+printf",{C_UINT}) and define_c_proc(open_dll("libc.so"),
"+printf",{C_UINT}).  Neither was able to link to the C function, not even
when I changed C_UINT to C_POINTER.  I gave up and just recoded the GTK 
routine I was after in Euphoria.  I'm sure there are other variadics out there
that I won't be able to cheat so easily, so it's important for the community
that we find a way to prove that it works without rewriting the functions in
Euphoria.  If we can't (and so far we're 0 for 2), we may need a source
mod to enable that functionality.

Michael Sabal

new topic     » goto parent     » topic index » view message » categorize

9. Re: undefine_c_func (was: memory profiling)

Michael J. Sabal wrote:
> 
> Chris Bensler wrote:
> > 
> > Oops, I missed poking the null terminator (not needed for printf anyway)
> > And I also didn't declare printf as cdecl "+printf" (all variadic functions
> > are cdecl)
> > 
> 
> I tried running your code with these modifications under 2 scenarios:  
> define_c_proc("","+printf",{C_UINT}) and define_c_proc(open_dll("libc.so"),
> "+printf",{C_UINT}).  Neither was able to link to the C function, not even
> when I changed C_UINT to C_POINTER.  I gave up and just recoded the GTK 
> routine I was after in Euphoria.  I'm sure there are other variadics out there
> that I won't be able to cheat so easily, so it's important for the community
> that we find a way to prove that it works without rewriting the functions in
> Euphoria.  If we can't (and so far we're 0 for 2), we may need a source
> mod to enable that functionality.

You might need to import as "+_printf", since that's what compilers usually 
do with cdecl exports.

You could also use fptr.e (in the archives) which uses assembly to push
the args.  You can use define_c_var to simply get the address of the 
exported function.

The easier solution is probably Pete's, however.

Matt

new topic     » goto parent     » topic index » view message » categorize

10. Re: undefine_c_func (was: memory profiling)

Pete Lomax wrote:
> 
> On Mon, 20 Nov 2006 05:32:34 -0800, Chris Bensler
> <guest at RapidEuphoria.com> wrote:
> 
> >There is no need for these kinds of hacks, 
> Oh/Uh?

Sorry Pete, I didn't mean it to offend. My perception of a hack is any code that
'cheats' it's way around a problem.
Not necessarily a bad solution, just not the best one.

> >variadic functions are fairly simple to interface with once you know how.
> >I'm mostly going from memory and a lack of available informaton, but..
> OK, I'm listening...
> >

<SNIP>

All of the information I gave was derived directly from online research the day
I wrote the post to confirm my memory, just so ya know I'm not talking through my
hat ;) I'm quite sure it will work.

I'll figure it out and get back to you guys.

<snip>

> [1] Far as I know, in most languages (not Eu, of course), parameters
> are pushed onto the stack, and the stack is kept machine-word aligned
> by default. There's no "array" involved, though they do end up next to
> each other by the time the function sees them.

Yes they are pushed onto the stack. Which reminds me, the array may need to be
reversed.

Yes the array/stack is machine-word aligned. On a 64-bit machine I suppose all
types would be promoted to doubles.
On 32-bit x86, a word is a 4 byte INT and a DOUBLE would still be aligned.

> [2] It is NOT a mandate that a (C) function must crash when passed
> arguments of the wrong type. Any "responsibility" clearly lies with
> the caller, not the callee.

No it's not a mandate, it's a trait.
All vararg handling is done within the function. Not done by the caller.
The types and sizes of the args are determined by the caller, by an undefined
means.

Yes this is kinda backwards, but it was a design compromise, so that a
programmer doesn't have to do all the dirty work everytime a variadic is called.

> [3] Clearly printf will print rubbish, and/or ignore excess arguments.
> Inherently it has /no/ type checking abilities. Quite how one might
> print 0 when you 0-terminate this fictional array is a mystery to me.

printf does have type checking abilities. It uses the string formatting flags to
determine how many and what types the args should be.

Terminating the array is not nessecary for printf(), the number of args for
printf is implicit in the string format.

How do you print 0 with a 0-terminated string? :)
Same thing just INTs instead of CHARs

I should have said null-terminated, not 0-terminated.
If the designer of the function wanted to allow NULL to be a valid argument then
they would probably require the argument count to be passed as the last named
parameter.



Chris Bensler
~ The difference between ordinary and extraordinary is that little extra ~
http://empire.iwireweb.com - Empire for Euphoria

new topic     » goto parent     » topic index » view message » categorize

11. Re: undefine_c_func (was: memory profiling)

Chris Bensler wrote:

> No it's not a mandate, it's a trait.
> All vararg handling is done within the function. Not done by the caller.
> The types and sizes of the args are determined by the caller, by an undefined
> means.

I mean defined by the 'callee' :S
I shoulda stuck with 'function' :P


Chris Bensler
~ The difference between ordinary and extraordinary is that little extra ~
http://empire.iwireweb.com - Empire for Euphoria

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu