[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[OT] JNA Help - LPDWORD

Daniel Berger

1/29/2008 5:19:00 AM

Hi all,

Does anyone happen to know the JNA equivalent of [24].pack('L')? I need
to pass a LPDWORD (pointer to a long) to a function.

Here's the code snippet I'm trying to make work. I'm pretty sure it's
failing because 'num' isn't a proper data structure.

require 'java'

Advapi32 = com.sun.jna.NativeLibrary.getInstance('advapi32')
GetUserNameA = Advapi32.getFunction('GetUserNameA')

buf = java.nio.ByteBuffer.allocate(24)
num = [24].pack('L')

p GetUserNameA.invokeInt([buf, num].to_java) # Fails

buf = String.from_java_bytes(buf.array)

p buf.strip # Empty?
p num.unpack('L').first # Should be length of user

Here's the equivalent win32-api script:

require 'win32/api'
include Win32

GetUserNameA = API.new('GetUserNameA', 'PP', 'I', 'advapi32')
buf = 0.chr * 24
num = [buf.size].pack('L')

p GetUserNameA.call(buf, num)

p buf.strip
p num.unpack('L').firs

Thanks,

Dan


6 Answers

Tim Pease

1/29/2008 3:17:00 PM

0

On Jan 28, 2008, at 10:18 PM, Daniel Berger wrote:

> Hi all,
>
> Does anyone happen to know the JNA equivalent of [24].pack('L')? I
> need to pass a LPDWORD (pointer to a long) to a function.
>

Fire off an e-mail to Rich Kilmer. I do believe he did quite a bit of
code bridging ruby and JNA.

Blessings,
TwP


Leif Eriksen

1/31/2008 12:38:00 AM

0

Some background - bear with me

So I'm writing my first little library (module) in ruby, for a
play-project in rails.

The library is for color management related functions, and its first
method is to
provide a color 'gradient', which I use for images where the colors smoothly
change from a to b in as many steps as I require

for example, to get from html rgb color #010101 to #444444 in 5 'steps',
we would do

ColorManagement.gradient(#010101, #444444, 5) # will used named params
in version 2!

and it would return

["#010101", "#0e0e0e", "#1b1b1b", "#282828", "#353535", "#444444"]

The method supports leading '0x' chars as well, and prepends the leading
chars (if any) to the
entries in the result array.

And this is all cool, until I did this

start = '#010101'
finish = '#444444'
ColorGradient.gradient(start, finish , 5)
pp start "#{start}"
pp "finish #{finish }"

and I see this

"start 010101"
"finish 444444"

The '#''s are gone. Internally the library is stripping these off to make
splitting into RGB channels easier, and it does the stripping like this

def self.gradient(hex_start="000000", hex_end="FFFFFF", steps=256)
[hex_start,hex_end].each do |hex|
hex.sub!(/^(0[xX]|#)/) do |match|
match = '' # remove any leading # or Ox

So the strings that are passed in are permanently munged by the sub! .
OK I get that, and to solve it I did this

def self.gradient(param_start="000000", param_end="FFFFFF", steps=256)
#make local copies of parameters
hex_start = String.new(param_start)
hex_end = String.new(param_end)

[hex_start,hex_end].each do |hex|
hex.sub!(/^(0[xX]|#)/) do |match|
...

So in effect I copy the parameter strings into local vars, to avoid
munging what the user passes me and annoying them.

But is this the ruby way ? Is this the idiomatic way to avoid
side-effects on objects passed in as parameters ?

Cheers
Leif

Adam Shelly

1/31/2008 1:20:00 AM

0

On 1/30/08, Leif Eriksen <leif.eriksen@bigpond.com> wrote:
>
> def self.gradient(hex_start="000000", hex_end="FFFFFF", steps=256)
> [hex_start,hex_end].each do |hex|
> hex.sub!(/^(0[xX]|#)/) do |match|
> match = '' # remove any leading # or Ox
>
> So the strings that are passed in are permanently munged by the sub! .
> OK I get that, and to solve it I did this
>
> def self.gradient(param_start="000000", param_end="FFFFFF", steps=256)
> #make local copies of parameters
> hex_start = String.new(param_start)
> hex_end = String.new(param_end)
>
> [hex_start,hex_end].each do |hex|
> hex.sub!(/^(0[xX]|#)/) do |match|
> ...
>
> So in effect I copy the parameter strings into local vars, to avoid
> munging what the user passes me and annoying them.
>
> But is this the ruby way ? Is this the idiomatic way to avoid
> side-effects on objects passed in as parameters ?
>

I'm no idiom expert, but I'd say no. You are correct that if you are
going to do a destructive operation without affecting the caller, you
need to make a copy. But usually, it's simpler to just get a modified
copy by calling the non-destructive version:


def self.gradient(hex_start="000000", hex_end="FFFFFF", steps=256)
hex_start=hex_start.gsub(/^(0[xX]|#)/,'')
hex_end=hex_end.gsub(/^(0[xX]|#)/,'')
...
end

-Adam

ara.t.howard

1/31/2008 6:51:00 AM

0


On Jan 30, 2008, at 5:37 PM, Leif Eriksen wrote:

> But is this the ruby way ? Is this the idiomatic way to avoid side-
> effects on objects passed in as parameters ?


yes. i might just use

local = param.dup

or

local = "#{ param }"

though

regards.


a @ http://codeforp...
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama



Leif Eriksen

2/1/2008 10:19:00 AM

0

ara howard wrote:
>
>
> yes. i might just use
>
> local = param.dup
>
Super - thanx, both ideas are great - and I need to work out why I chose
to use sub!

L

Robert Klemme

2/1/2008 10:56:00 AM

0

2008/1/31, Leif Eriksen <leif.eriksen@bigpond.com>:
> Some background - bear with me
>
> So I'm writing my first little library (module) in ruby, for a
> play-project in rails.
>
> The library is for color management related functions, and its first
> method is to
> provide a color 'gradient', which I use for images where the colors smoothly
> change from a to b in as many steps as I require
>
> for example, to get from html rgb color #010101 to #444444 in 5 'steps',
> we would do
>
> ColorManagement.gradient(#010101, #444444, 5) # will used named params
> in version 2!
>
> and it would return
>
> ["#010101", "#0e0e0e", "#1b1b1b", "#282828", "#353535", "#444444"]
>
> The method supports leading '0x' chars as well, and prepends the leading
> chars (if any) to the
> entries in the result array.
>
> And this is all cool, until I did this
>
> start = '#010101'
> finish = '#444444'
> ColorGradient.gradient(start, finish , 5)
> pp start "#{start}"
> pp "finish #{finish }"
>
> and I see this
>
> "start 010101"
> "finish 444444"
>
> The '#''s are gone. Internally the library is stripping these off to make
> splitting into RGB channels easier, and it does the stripping like this
>
> def self.gradient(hex_start="000000", hex_end="FFFFFF", steps=256)
> [hex_start,hex_end].each do |hex|
> hex.sub!(/^(0[xX]|#)/) do |match|
> match = '' # remove any leading # or Ox
>
> So the strings that are passed in are permanently munged by the sub! .
> OK I get that, and to solve it I did this
>
> def self.gradient(param_start="000000", param_end="FFFFFF", steps=256)
> #make local copies of parameters
> hex_start = String.new(param_start)
> hex_end = String.new(param_end)
>
> [hex_start,hex_end].each do |hex|
> hex.sub!(/^(0[xX]|#)/) do |match|
> ...
>
> So in effect I copy the parameter strings into local vars, to avoid
> munging what the user passes me and annoying them.
>
> But is this the ruby way ? Is this the idiomatic way to avoid
> side-effects on objects passed in as parameters ?

I'd say, this is generally considered bad OO. A better solution would
be to create a class Color that provides methods to do all the
conversions. E.g.

Color = Struct.new :red, :green, :blue do

# will accept either
# a single string with hex number
# a single fixnum (0x000000 - 0xFFFFFF, larger values are truncated)
# three fixnums
# three strings
def initialize(*a)
case a.length
when 3
self.red,
self.green,
self.blue = a.map {|v| arg2bin(v) % 0x100}
when 1
tmp = arg2bin a.first
raise ArgumentError, "Negative value" if tmp < 0
self.red = (tmp >> 16) % 0x100
self.green = (tmp >> 8) % 0x100
self.blue = tmp % 0x100
else
raise ArgumentError,
"Need either a single string with hex number, a single
Fixnum or three separate Fixnums or hex Strings"
end
end

def to_hex
sprintf "%02x%02x%02x", red, green, blue
end

def to_s
sprintf "#%02x%02x%02x", red, green, blue
end

def &(color)
Color.new red & color.red,
green & color.green,
blue & color.blue
end

def |(color)
Color.new red | color.red,
green | color.green,
blue | color.blue
end

private
def arg2bin(a)
case a
when Fixnum
a
when String
a.to_i 16
end
end
end

This is just a sample implementation. You might as well change
internal representation to a single Fixnum etc. Then add methods as
you need them.

Kind regards

robert

--
use.inject do |as, often| as.you_can - without end