Using a DLL that wants a function pointer

I want to use a DLL with Ruby (Win32). This DLL has X number of functions,
and one of these takes a function pointer. The DLL will call this
callback-function when some data arrives. I cannot figure out how to do this
in Ruby. Is it possible? If not, any tips on how to circumvent this
restriction? _Any_ hints appreciated.

/D

daniel åkerud wrote:

I want to use a DLL with Ruby (Win32). This DLL has X number of
functions,
and one of these takes a function pointer. The DLL will call this
callback-function when some data arrives. I cannot figure out how to do
this
in Ruby. Is it possible? If not, any tips on how to circumvent this
restriction? _Any_ hints appreciated.

It is with fear and trembling that I post here, but I did not want
nothing to be said, so take this with the proverbial salt lick until
someone that knows can answer.

Using pointers from an interpreted language is not something that should
work and, if it does, I expect that it will be ugly.

Here is what I would do if I had no other way to do, and, at the moment,
I don't. I would make an intermediary program that handles the
pointers and talks to both your ruby app and the DLL in question using
something simple. You did not say which language the DLL was written
in, so I will assume that it is C/C++. Personally, I work with Delphi
and a pascal DLL is compiled a bit differently. Also, if it is compiled
for windows, they use the FAR PASCAL call to make it run faster, though
Mr. Bill changed the name because he hates pascal.

You can experiment to find how it all works together but it is at least
something. I admit that it is ugly in the extreme, but it is a place to
start if nothing more elegant gets offered.

GL!

···

--
Posted via http://www.ruby-forum.com/\.

I haven't tried it before, but look into Win32::API::Callback. Most of
my googling returned threads where people were having problems with
it, but that might give you examples to get started with. Here's one
of them:
http://rubyforge.org/pipermail/win32utils-devel/2008-January/000985.html

Look for where SNMPAPI_CALLBACK is defined. It appears that Callback
takes two arguments - the first is the parameter signature notated the
same as when you use an API method. The second would be the return
signature. Following that is the body of the callback as a block.

···

On Jan 24, 9:10 am, daniel åkerud <daniel.ake...@gmail.com> wrote:

[Note: parts of this message were removed to make it a legal post.]

I want to use a DLL with Ruby (Win32). This DLL has X number of functions,
and one of these takes a function pointer. The DLL will call this
callback-function when some data arrives. I cannot figure out how to do this
in Ruby. Is it possible? If not, any tips on how to circumvent this
restriction? _Any_ hints appreciated.

/D

Thanks for the answers,

Today I have been working with creating Ruby extensions, and I got this
idea: What about I pass a Proc.new object to a method in the extension, and
when the extension gets a callback from the DLL, it calls the Proc object.
This would work right? I havn't seen an example of an extension that manages
a Proc object though and calls it, but if someone says this sounds
reasonable i'll do this.

/D

···

On Jan 24, 2008 7:45 PM, yermej <yermej@gmail.com> wrote:

On Jan 24, 9:10 am, daniel åkerud <daniel.ake...@gmail.com> wrote:
> [Note: parts of this message were removed to make it a legal post.]
>
> I want to use a DLL with Ruby (Win32). This DLL has X number of
functions,
> and one of these takes a function pointer. The DLL will call this
> callback-function when some data arrives. I cannot figure out how to do
this
> in Ruby. Is it possible? If not, any tips on how to circumvent this
> restriction? _Any_ hints appreciated.
>
> /D

I haven't tried it before, but look into Win32::API::Callback. Most of
my googling returned threads where people were having problems with
it, but that might give you examples to get started with. Here's one
of them:
http://rubyforge.org/pipermail/win32utils-devel/2008-January/000985.html

Look for where SNMPAPI_CALLBACK is defined. It appears that Callback
takes two arguments - the first is the parameter signature notated the
same as when you use an API method. The second would be the return
signature. Following that is the body of the callback as a block.

I think this is important in this context: The callback is called from
another thread, i.e. the DLL creates a thread that reads data in the
background, and when data arrives it calls the callback. Would this be a
problem if the Ruby extension calls the Proc object from another thread, and
if so, how to solve it...

/D

···

On Jan 24, 2008 9:45 PM, daniel åkerud <daniel.akerud@gmail.com> wrote:

On Jan 24, 2008 7:45 PM, yermej <yermej@gmail.com> wrote:

> On Jan 24, 9:10 am, daniel åkerud <daniel.ake...@gmail.com> wrote:
> > [Note: parts of this message were removed to make it a legal post.]
> >
> > I want to use a DLL with Ruby (Win32). This DLL has X number of
> functions,
> > and one of these takes a function pointer. The DLL will call this
> > callback-function when some data arrives. I cannot figure out how to
> do this
> > in Ruby. Is it possible? If not, any tips on how to circumvent this
> > restriction? _Any_ hints appreciated.
> >
> > /D
>
> I haven't tried it before, but look into Win32::API::Callback. Most of
> my googling returned threads where people were having problems with
> it, but that might give you examples to get started with. Here's one
> of them:
> http://rubyforge.org/pipermail/win32utils-devel/2008-January/000985.html
>
> Look for where SNMPAPI_CALLBACK is defined. It appears that Callback
> takes two arguments - the first is the parameter signature notated the
> same as when you use an API method. The second would be the return
> signature. Following that is the body of the callback as a block.
>
>
Thanks for the answers,

Today I have been working with creating Ruby extensions, and I got this
idea: What about I pass a Proc.new object to a method in the extension,
and when the extension gets a callback from the DLL, it calls the Proc
object. This would work right? I havn't seen an example of an extension that
manages a Proc object though and calls it, but if someone says this sounds
reasonable i'll do this.

/D

<snip>

I think this is important in this context: The callback is called from
another thread, i.e. the DLL creates a thread that reads data in the
background, and when data arrives it calls the callback. Would this be a
problem if the Ruby extension calls the Proc object from another thread, and
if so, how to solve it...

At the moment, you don't. Windows callbacks occur in their own native
thread. The Ruby interpreter isn't thread safe. You'll get one
callback call to work, but after that it will probably segfault.

Heesob is working on this for the C side of the house to see if he can
come up with a way to make it work. In the meantime, I'm going to see
if I can get win32-api ported to JRuby using JNA this weekend. That
*should* work, though it means you'll have to use JRuby to use it,
which may not be such a bad thing. :slight_smile:

Regards,

Dan

···

On Jan 24, 1:52 pm, "daniel åkerud" <daniel.ake...@gmail.com> wrote:

What if I provide a polling-mechanism, i.e. the Ruby-extension puts all data
from the callback in a queue, and the Ruby-script poll()s periodically to
see if there is any data. In this case, to Ruby, everything will happen in
the same thread. Indeed this removes the callback interface Ruby-Script ->
Ruby-Extension (which indeed is the subject...), but it circumvents the
threading-problem. Would it work?

/D

···

On Jan 24, 2008 10:11 PM, Daniel Berger <djberg96@gmail.com> wrote:

On Jan 24, 1:52pm, "daniel åkerud" <daniel.ake...@gmail.com> wrote:

<snip>

> I think this is important in this context: The callback is called from
> another thread, i.e. the DLL creates a thread that reads data in the
> background, and when data arrives it calls the callback. Would this be a
> problem if the Ruby extension calls the Proc object from another thread,
and
> if so, how to solve it...

At the moment, you don't. Windows callbacks occur in their own native
thread. The Ruby interpreter isn't thread safe. You'll get one
callback call to work, but after that it will probably segfault.

Heesob is working on this for the C side of the house to see if he can
come up with a way to make it work. In the meantime, I'm going to see
if I can get win32-api ported to JRuby using JNA this weekend. That
*should* work, though it means you'll have to use JRuby to use it,
which may not be such a bad thing. :slight_smile:

Regards,

Dan

daniel åkerud wrote:

···

On Jan 24, 2008 10:11 PM, Daniel Berger <djberg96@gmail.com> wrote:

On Jan 24, 1:52pm, "daniel åkerud" <daniel.ake...@gmail.com> wrote:

<snip>

I think this is important in this context: The callback is called from
another thread, i.e. the DLL creates a thread that reads data in the
background, and when data arrives it calls the callback. Would this be a
problem if the Ruby extension calls the Proc object from another thread,

and

if so, how to solve it...

At the moment, you don't. Windows callbacks occur in their own native
thread. The Ruby interpreter isn't thread safe. You'll get one
callback call to work, but after that it will probably segfault.

Heesob is working on this for the C side of the house to see if he can
come up with a way to make it work. In the meantime, I'm going to see
if I can get win32-api ported to JRuby using JNA this weekend. That
*should* work, though it means you'll have to use JRuby to use it,
which may not be such a bad thing. :slight_smile:

Regards,

Dan

What if I provide a polling-mechanism, i.e. the Ruby-extension puts all data
from the callback in a queue, and the Ruby-script poll()s periodically to
see if there is any data. In this case, to Ruby, everything will happen in
the same thread. Indeed this removes the callback interface Ruby-Script ->
Ruby-Extension (which indeed is the subject...), but it circumvents the
threading-problem. Would it work?

Yes, that would work if you make the data queue thread safe, probably using a Windows mutex (and wait with no timeout duration in the Ruby thread).

Best regards,

Jari Williamsson