1. How to catch integer 64 bit return variable type

Dear all,

I'm building a small application using sqlite3 API. The application run 
smoothly until an integer field consists a value greater than 32 bit 
integer was found on database. Particularly, sqlite3 API has some 
functions with 64 bit integer return value (long long int variable 
type), but it can't be catch properly in Euphoria since library dll.e 
does not provide any constant variable for handling 64 bit integer 
return value at all. Trying one of both C_FLOAT and C_DOUBLE only return 
a 'nan' value.

Any information, suggestion or an idea to solve this problem?

PS: Sorry for my bad english....

Doni

new topic     » topic index » view message » categorize

2. Re: How to catch integer 64 bit return variable type

D. Darmawan wrote:

> Dear all,
> 
> I'm building a small application using sqlite3 API. The application run 
> smoothly until an integer field consists a value greater than 32 bit 
> integer was found on database. Particularly, sqlite3 API has some 
> functions with 64 bit integer return value (long long int variable 
> type), but it can't be catch properly in Euphoria since library dll.e 
> does not provide any constant variable for handling 64 bit integer 
> return value at all. Trying one of both C_FLOAT and C_DOUBLE only return 
> a 'nan' value.
> 
> Any information, suggestion or an idea to solve this problem?

You need functions like these:
global function peek8u (atom addr)
   -- returns an *unsigned* 8-byte integer
   return peek4u(addr+4)*#100000000 + peek4u(addr)
end function

global function peek8s (atom addr)
   -- returns a *signed* 8-byte integer
   atom ret

   ret = peek4u(addr+4)*#100000000 + peek4u(addr)
   if ret > #7FFFFFFFFFFFFFFF then
      ret -= #10000000000000000
   end if
   return ret
end function


-- Then in your program use code such as:
myAPIfunc = define_c_func(myDLL, "desired_function", {C_POINTER, C_POINTER},
C_LONG)

lpMyVar1 = allocate(8)
lpMyVar2 = allocate(8)

x = c_func(myAPIfunc, {lpMyVar1, lpMyVar2})

myVar1 = peek8u(lpMyVar1)
myVar2 = peek8s(lpMyVar2)

free(lpMyVar1)
free(lpMyVar2)


Regards,
   Juergen

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

3. Re: How to catch integer 64 bit return variable type

Thanks your quick response Juergen,

I try to make my expectation more understandable.
Assume that C function in API library is like this:

long long int desired_function(any_struct_value*);

that will return any 64 bit integer value.

Then I link and call that C function in my Eu code:

myAPIfunc = define_c_func(myDLL, "desired_function", {C_POINTER}, C_LONG)

x = c_func(myAPIfunc, {lpMyVar1})

 

Now, my question is: 
How to catch the 64bit integer return value from myAPIfunc and assign it into
'x' variable???

Doni

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

4. Re: How to catch integer 64 bit return variable type

D. Darmawan wrote:

> Thanks your quick response Juergen,
> 
> I try to make my expectation more understandable.
> Assume that C function in API library is like this:
> 
> }}}
<eucode>
> long long int desired_function(any_struct_value*);
> </eucode>
{{{

> that will return any 64 bit integer value.
> 
> Then I link and call that C function in my Eu code:
> 
> }}}
<eucode>
> myAPIfunc = define_c_func(myDLL, "desired_function", {C_POINTER}, C_LONG)
> 
> x = c_func(myAPIfunc, {lpMyVar1})
> </eucode>
{{{
 
> 
> Now, my question is: 
> How to catch the 64bit integer return value from myAPIfunc and assign it into
> 'x' variable???

I see. Unfortunately, for this case I don't have a solution.
However, if we declare the problem "insoluble", then Matt will solve it. :)

Regards,
   Juergen

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

5. Re: How to catch integer 64 bit return variable type

Juergen Luethje wrote:
> 
> D. Darmawan wrote:
> 
> > Thanks your quick response Juergen,
> > 
> > I try to make my expectation more understandable.
> > Assume that C function in API library is like this:
> > 
> > }}}
<eucode>
> > long long int desired_function(any_struct_value*);
> > </eucode>
{{{

> > that will return any 64 bit integer value.
> > 
> > Then I link and call that C function in my Eu code:
> > 
> > }}}
<eucode>
> > myAPIfunc = define_c_func(myDLL, "desired_function", {C_POINTER}, C_LONG)
> > 
> > x = c_func(myAPIfunc, {lpMyVar1})
> > </eucode>
{{{
 
> > 
> > Now, my question is: 
> > How to catch the 64bit integer return value from myAPIfunc and assign it
> > into
> > 'x' variable???
> 
> I see. Unfortunately, for this case I don't have a solution.
> However, if we declare the problem "insoluble", then Matt will solve it. :)
> 
> Regards,
>    Juergen

I didn't test this because I don't have functions that return 64-bit
integers. However, it should work using inline assembly.
As far as I know, 64-bit values are returned in EDX:EAX. So the idea is
to write some assembly that will call the function and store EDX and EAX
in known places you'll peek4u() on return.
constant asm64_wrapper={
0,0,0,0, -- +0: address of function to call
0,0,0,0, -- +4: argument passed to it
0,0,0,0, -- +8: placeholder for EAX
0,0,0,0, -- +12:placeholder for EDX
#FF,#35, -- +16:push dword mem
0,0,0,0, -- +18:patch with addr of second data dword
#FF,#15, -- +22:call near dword
0,0,0,0, -- +24:patch with addr of 1st data dword
#89,#D5, -- +28:mov dword [mem],EDX
0,0,0,0, -- +30:patch with addr of 4th dword
#A3,     -- +34:mov dword [mem],EAX
0,0,0,0, -- +35:patch with 3rd adr
#C3      -- +39:ret near
}
constant wrapper_address = allocate(length(asm64_wrapper))
poke(wrapper_address,asm64_wrapper)
-- patch position
poke4(wrapper_address+18,wrapper_address+4)
poke4(wrapper_address+24,wrapper_address)
poke4(wrapper_address+30,wrapper_address+8)
poke4(wrapper_address+35,wrapper_address+12)

atom my_callback,my_arg
my_callback = callback(myAPIfunc)
my_arg = allocate(length_of_my_struct)
poke(my_arg,my_struct) 
-- or whatever is more convenient, depending on the struct layout

constant toHiDword = 65536*65536 -- 2^32

function get_longlongsigned(atom callback,atom arg)
   atom loDword,hiDword
   poke4(wrapper_address,callback)
   poke4(wrapper_address+4,arg)
   call(wrapper_address+16) -- code to exec starts there
   loDword=peek4u(wrapper_address+8)
   hiDword=peek4s(wrapper_address+12)
return loDword + hiDword * toHiDword
end function

atom result
result=get_longlongsigned(my_callback,my_arg)


Of course, variants of the asm64_wrapper sequence will have to be devised
whenever the prototype changes. Change peek4s() to peek4u() to retrieve
unsigned long longs.

CChris

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

6. Re: How to catch integer 64 bit return variable type

Juergen Luethje wrote:
> 
> D. Darmawan wrote: 
myAPIfunc = define_c_func(myDLL, "desired_function", {C_POINTER}, C_LONG)

x = c_func(myAPIfunc, {lpMyVar1})

 
> > 
> > Now, my question is: 
> > How to catch the 64bit integer return value from myAPIfunc and assign it
> > into
> > 'x' variable???
> 
> I see. Unfortunately, for this case I don't have a solution.
> However, if we declare the problem "insoluble", then Matt will solve it. :)

Sure, no pressure, right? :)

My solution would be to either write a wrapper dll, or to call the dll
with something along the lines of fptr.e.  With either method, I'd
return the value to a memory buffer that would be read by something 
like Juergen's peek8 routine.

So a C-based wrapper function might look something like:

void myAPIfuncWrapper( long long * retval, int * api_param ){
    *retval = myAPIfunc(api_param);
}

I found this:
http://www.ecos.sourceware.org/ml/gdb/2000-q1/msg00660.html
2. As far as I can tell, all i386 targets return `long long' values in
   eax (low word) and edx (high word).  This makes sense since this is
   the convention used by the machine instructions themselves.  The
   relevant GCC code suggests that in addition to eax and edx, ecx
   might also be used for 12-byte values (then edx is the "middle"
   word, and ecx the high word).  But since GCC doesn't have a 12-byte
   integer type (would that make sense?) this should never occur.
   However, the full 12-byte range is used for returning extended
   floating-point numbers (`long double').  Right now this is only
   implemented for AIX, Linux and DJGPP, but this should be made more
   general.

Matt

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

7. Re: How to catch integer 64 bit return variable type

CChris wrote:
> 
> I didn't test this because I don't have functions that return 64-bit
> integers. However, it should work using inline assembly.
> As far as I know, 64-bit values are returned in EDX:EAX. So the idea is
> to write some assembly that will call the function and store EDX and EAX
> in known places you'll peek4u() on return.
> }}}
<eucode>
> constant asm64_wrapper={
> 0,0,0,0, -- +0: address of function to call
> 0,0,0,0, -- +4: argument passed to it
> 0,0,0,0, -- +8: placeholder for EAX
> 0,0,0,0, -- +12:placeholder for EDX
> #FF,#35, -- +16:push dword mem
> 0,0,0,0, -- +18:patch with addr of second data dword
> #FF,#15, -- +22:call near dword
> 0,0,0,0, -- +24:patch with addr of 1st data dword
> #89,#D5, -- +28:mov dword [mem],EDX
> 0,0,0,0, -- +30:patch with addr of 4th dword
> #A3,     -- +34:mov dword [mem],EAX
> 0,0,0,0, -- +35:patch with 3rd adr
> #C3      -- +39:ret near
> }
> constant wrapper_address = allocate(length(asm64_wrapper))
> poke(wrapper_address,asm64_wrapper)
> -- patch position
> poke4(wrapper_address+18,wrapper_address+4)
> poke4(wrapper_address+24,wrapper_address)
> poke4(wrapper_address+30,wrapper_address+8)
> poke4(wrapper_address+35,wrapper_address+12)
> 
> atom my_callback,my_arg
> my_callback = callback(myAPIfunc)
> my_arg = allocate(length_of_my_struct)
> poke(my_arg,my_struct) 
> -- or whatever is more convenient, depending on the struct layout
> 
> constant toHiDword = 65536*65536 -- 2^32
> 
> function get_longlongsigned(atom callback,atom arg)
>    atom loDword,hiDword
>    poke4(wrapper_address,callback)
>    poke4(wrapper_address+4,arg)
>    call(wrapper_address+16) -- code to exec starts there
>    loDword=peek4u(wrapper_address+8)
>    hiDword=peek4s(wrapper_address+12)
> return loDword + hiDword * toHiDword
> end function
> 
> atom result
> result=get_longlongsigned(my_callback,my_arg)
> </eucode>
{{{

> 
> Of course, variants of the asm64_wrapper sequence will have to be devised
> whenever the prototype changes. Change peek4s() to peek4u() to retrieve
> unsigned long longs.
> 
> CChris

Thanks for your idea Chris...
I'll try it first...

Regards
Doni

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

8. Re: How to catch integer 64 bit return variable type

Matt Lewis wrote:

> Juergen Luethje wrote:

<snip>

>> However, if we declare the problem "insoluble", then Matt will solve it. :)
> 
> Sure, no pressure, right? :)

<snip>

Hi Matt,

I didn't want to put you under pressure. If my post lokked
like that or had such a side effect, then I'm really sorry.

Regards,
   Juergen

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

9. Re: How to catch integer 64 bit return variable type

Juergen Luethje wrote:
> 
> D. Darmawan wrote:
> 
> > Thanks your quick response Juergen,
> > 
> > I try to make my expectation more understandable.
> > Assume that C function in API library is like this:
> > 
> > }}}
<eucode>
> > long long int desired_function(any_struct_value*);
> > </eucode>
{{{

> > that will return any 64 bit integer value.
> > 
> > Then I link and call that C function in my Eu code:
> > 
> > }}}
<eucode>
> > myAPIfunc = define_c_func(myDLL, "desired_function", {C_POINTER}, C_LONG)
> > 
> > x = c_func(myAPIfunc, {lpMyVar1})
> > </eucode>
{{{
 
> > 
> > Now, my question is: 
> > How to catch the 64bit integer return value from myAPIfunc and assign it
> > into
> > 'x' variable???
> 
> I see. Unfortunately, for this case I don't have a solution.
> However, if we declare the problem "insoluble", then Matt will solve it. :)
> 
> Regards,
>    Juergen


Hi

This is interesting.

Are you using the sqlite3 wrappers?

Are you trying to get a large signed integer from a database query, or as
a return value from one of the other functions?

The reason I ask is that database queries are returned as text values in
sqlite3,
so you have to do the conversion afterwards.

However, if you are using functions not yet wrapped in eusqlite3, and you do
manage to wrap them, I would be more than happy to add them to eusqlite3
library.

Chris

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

10. Re: How to catch integer 64 bit return variable type

ChrisBurch2 wrote:

> Juergen Luethje wrote:
> > 
> > D. Darmawan wrote:
> > 
> > > Thanks your quick response Juergen,
> > > 
> > > I try to make my expectation more understandable.
> > > Assume that C function in API library is like this:
> > > 
> > > }}}
<eucode>
> > > long long int desired_function(any_struct_value*);
> > > </eucode>
{{{

> > > that will return any 64 bit integer value.
> > > 
> > > Then I link and call that C function in my Eu code:
> > > 
> > > }}}
<eucode>
> > > myAPIfunc = define_c_func(myDLL, "desired_function", {C_POINTER}, C_LONG)
> > > 
> > > x = c_func(myAPIfunc, {lpMyVar1})
> > > </eucode>
{{{
 
> > > 
> > > Now, my question is: 
> > > How to catch the 64bit integer return value from myAPIfunc and assign it
> > > into
> > > 'x' variable???
> > 
> > I see. Unfortunately, for this case I don't have a solution.
> > However, if we declare the problem "insoluble", then Matt will solve it. :)
> > 
> > Regards,
> >    Juergen
> 
> 
> Hi
> 
> This is interesting.
> 
> Are you using the sqlite3 wrappers?

No, I don't do so. I probably expressed myself somewhat unclear.

> Are you trying to get a large signed integer from a database query, or as
> a return value from one of the other functions?

As far as I can see, the peek8u() and peek8s() functions that I posted are
only useful when a parameter of a sqlite function is a _pointer_ to a
64-bit integer. Is this sometimes the case?

> The reason I ask is that database queries are returned as text values in
> sqlite3,
> so you have to do the conversion afterwards.
> 
> However, if you are using functions not yet wrapped in eusqlite3, and you do
> manage to wrap them, I would be more than happy to add them to eusqlite3
> library.

Unfortunately, I almost don't know anything about sqlite.

Regards,
   Juergen

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

11. Re: How to catch integer 64 bit return variable type

Juergen Luethje wrote:
> 
> Matt Lewis wrote:
> 
> > Juergen Luethje wrote:
> 
> <snip>
> 
> >> However, if we declare the problem "insoluble", then Matt will solve it. :)
> > 
> > Sure, no pressure, right? :)
> 
> <snip>
> 
> Hi Matt,
> 
> I didn't want to put you under pressure. If my post lokked
> like that or had such a side effect, then I'm really sorry.

No, of course not.  I was flattered, really. :)

Matt

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

12. Re: How to catch integer 64 bit return variable type

ChrisBurch2 wrote:
> 
> Hi
> 
> This is interesting.
> 
> Are you using the sqlite3 wrappers?
> Are you trying to get a large signed integer from a database query, or as
> a return value from one of the other functions?

Yes Chris, I'm using sqlite3 wrapper, and the problem was occurred when I'm
trying
to get a large signed integer in one numeric field from a database query
 
> The reason I ask is that database queries are returned as text values in
> sqlite3,
> so you have to do the conversion afterwards.

Really??? FYI, I performed sqlite_step and sqlite_column_int that will return an
integer value from certain field. 
I think what you're talking about sqlite_get_table function. Yes, I know that
function
will return text value and we can pointing it out with data[row][col] in 
sequence format. But it's memory greedy while it's returning a huge rowset.
 
> However, if you are using functions not yet wrapped in eusqlite3, and you do
> manage to wrap them, I would be more than happy to add them to eusqlite3
> library.
> 
> Chris

I'd love too, Chris. That is a great idea. Ability to returning value in big
integer
from some functions may be placed in first priority, I think. And then, making
some
functions for handling query function customization is a good idea (I've written
this
one in my modified eusqlite3 wrapper).

Regards,
Doni

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

13. Re: How to catch integer 64 bit return variable type

D. Darmawan wrote:
> 
> ChrisBurch2 wrote:
> > 
> > Hi
> > 
> > This is interesting.
> > 
> > Are you using the sqlite3 wrappers?
> > Are you trying to get a large signed integer from a database query, or as
> > a return value from one of the other functions?
> 
> Yes Chris, I'm using sqlite3 wrapper, and the problem was occurred when I'm
> trying
> to get a large signed integer in one numeric field from a database query
>  
> > The reason I ask is that database queries are returned as text values in
> > sqlite3,
> > so you have to do the conversion afterwards.
> 
> Really??? FYI, I performed sqlite_step and sqlite_column_int that will return
> an 
> integer value from certain field. 

Yes, you're right. I've never used, or needed to use those functions in the
wrapper,
a clear case of disuse atrophy.

> I think what you're talking about sqlite_get_table function. Yes, I know that
> function
> will return text value and we can pointing it out with data[row][col] in 
> sequence format. But it's memory greedy while it's returning a huge rowset.
>  
> > However, if you are using functions not yet wrapped in eusqlite3, and you do
> > manage to wrap them, I would be more than happy to add them to eusqlite3
> > library.
> > 
> > Chris
> 
> I'd love too, Chris. That is a great idea. Ability to returning value in big
> integer 
> from some functions may be placed in first priority, I think. And then, making
> some 
> functions for handling query function customization is a good idea (I've
> written
> this
> one in my modified eusqlite3 wrapper).
> 
Are you able now to have 64 bit integers returned from sqlite_column_int calls?
And, will the same function return lower vaue (smaller bit count) integers?

If you are amenable, I would like to take a look at your modified functions,
for incorporation into the wrapper. post to crylex at gmail dot com

> Regards,
> Doni

Cheers

Chris

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

14. Re: How to catch integer 64 bit return variable type

Thanks Chris, Matt and Juergen,

I able to catch integer 64 bit return value now. It's solved.
I use Matt's fptr.e and made a little modification on call_cdcel function.
It's working on Linux and I've not tested this modification on Windows yet.

Here is the modified code on fptr.e I've made:
</eucode>
{{{

constant
fptr_cdecl_asm = {
    #60,                     --    0: pusha
    #BB,#00,#00,#00,#00,     --    1: mov ebx, paramcount (2)
    #B9,#00,#00,#00,#00,     --    6: mov ecx, params (7)
                             --    B: start: 
    #8B,#01,                 --    B: mov eax, [ecx]
    #50,                     --    D: push eax
    #83,#C1,#04,             --    E: add ecx, 4
    #4B,                     --   11: dec ebx
    #75,#F7,                 --   12: jnz start
    #FF,#15,#00,#00,#00,#00, --   14: call dword ptr [comfunc] (22) 
    #A3,#00,#00,#00,#00,     --   1A: mov [retpointer], eax (27)
#89,#15,#00,#00,#00,#00, --   1F: mov [retpointer], edx (33) --- additional
    bytecode
    #83, #C4, 00,            --   25: add esp 0 (39 or #27)
    #61,                     --   28: popa
    #C3},                    --   29: ret


fptr_cdecl_paramcount = 2,
fptr_cdecl_params = 7,
fptr_cdecl_funcptr = 22,
fptr_cdecl_retptrLo = 27,  --- fptr_cdecl_retptr
fptr_cdecl_retptrHi = 33,  --- additional new pointer
cdecl_retval = allocate(4),

fptr_cdecl_asm_addr = allocate( length( fptr_cdecl_asm ) + 20 * 4 )

constant
--- changed from #24 to #2A
fptr_cdecl_func = fptr_cdecl_asm_addr + #2A,          
fptr_cdecl_retvalLo = fptr_cdecl_asm_addr + #2A + 4,
fptr_cdecl_retvalHi = fptr_cdecl_asm_addr + #2A + 8,   --- insert new pointer
for edx value
fptr_cdecl_param_ptr = fptr_cdecl_asm_addr + #2A + 12  --- changed from #24 + 8 

poke( fptr_cdecl_asm_addr, fptr_cdecl_asm )
poke4( fptr_cdecl_asm_addr + fptr_cdecl_funcptr, fptr_cdecl_func )
poke4( fptr_cdecl_asm_addr + fptr_cdecl_params, fptr_cdecl_param_ptr )
poke4( fptr_cdecl_asm_addr + fptr_cdecl_retptrLo, fptr_cdecl_retvalLo )
poke4( fptr_cdecl_asm_addr + fptr_cdecl_retptrHi, fptr_cdecl_retvalHi ) ---
additional line


--/topic Calling functions
--/func call_cdecl( atom fptr, sequence params )
--/ret Return value of fptr
--/desc Calls a function using cdecl
--Calls a function using stdcall
--Use this to call a function using the stdcall calling convention when you
--have a pointer to the function.  This is the most common calling convention in
--Linux.  You can get the pointer to a function in a 
--.dll or .so using /b define_c_var() instead of /b define_c_func().  You should
--discard the return value if you call a routine that does not return a value.

global function call_cdecl( atom fptr, sequence params )
    atom ret
    
    -- store the pointer to the function
    poke4( fptr_cdecl_func, fptr )

    -- reverse the params for stdcall calling convention
    params = reverse(params)

    -- store the params
    poke4( fptr_cdecl_param_ptr, params )

    -- tell the asm how many params to push/pop
    poke4( fptr_cdecl_asm_addr + fptr_cdecl_paramcount, length(params) )
    poke( fptr_cdecl_asm_addr + #27, length(params) * 4) --- changed #21 to #27
    
    -- run the asm
    call( fptr_cdecl_asm_addr )

    -- get the value returned from the function
ret = peek4u( fptr_cdecl_retvalLo ) + peek4s( fptr_cdecl_retvalHi ) *
    #100000000 -- modified
    return ret

end function
</eucode>
{{{



And sqlite3 wrapper has been modified to:
include fptr.e
---
---
global function sqlite_column_int(atom db, atom stmt, integer column_num)
integer ptr
     
     ptr = define_c_var(sqlite3_dll, "sqlite3_column_int64")
     return call_cdecl(ptr, {stmt, column_num - 1 })

end function


Regards,
Doni

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

15. Re: How to catch integer 64 bit return variable type

D. Darmawan wrote:

> Thanks Chris, Matt and Juergen,
> 
> I able to catch integer 64 bit return value now. It's solved.
> I use Matt's fptr.e and made a little modification on call_cdcel function.
> It's working on Linux and I've not tested this modification on Windows yet.

[code snipped]

This is good news. smile
Especially, since in general the 64-bit stuff will become more and more
important.

Regards,
   Juergen

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

Search



Quick Links

User menu

Not signed in.

Misc Menu