Problem:
I'd like to use in my Ruby program an algorithm that is coded in C and exposed through a DLL.
I would like to treat the algorithm as a black box that I can call from within Ruby -- simply pass in the required parameters and use the result.
Ruby (both 1.8.7 and 1.9.3) has the Win32API
module which seems intended to make it quite easy to interface with dynamic libraries to do exactly what I'm after.
But the problem is that I can't seem to get the Win32API call to send back a string.
Details:
The third-party C function is CodeGen()
. It take 6 parameters, including a source string, an arbitrary string to serve as encryption key, and, for simplicity, 4 numerical parameters, one signed int, one unsigned long, and two unsigned shorts. From these, CodeGen() implements a black-box algorithm to return a resulting string.
The C prototype for CodeGen() is:
const char *CodeGen( int encryp_level,
const char *source_str, const char *encryp_key,
unsigned long param_a,
unsigned short param_b, unsigned short param_c
)
Note that both the input strings are constants, i.e. they are supplied to CodeGen() as strings -- so pointers to constant strings
The return value for CodeGen() is also a string, of fixed maximum length, so it will return a pointer.
My Question:
How do I go about setting up the call to CodeGen() and getting back the string it is supposed to generate?
My attempts:
The code below simply gives me integers as the return value, when I am expecting to obtain a string.
require 'Win32API'
codeGen = Win32API.new("encrypt.dll", "CodeGen", "ISSIII", "S")
ret_str = codeGen.Call(3, "foo", "bar", 0, 0, 0)
puts ret_str
However, instead of getting a string back, I get back an integer. Edit: Could this be a pointer?
Although I'm using Ruby 1.9.3 on Windows 7, 64-bit edition, I've also tested the above on Windows XP, 32-bits, and using Ruby 1.8.7, so I'm pretty sure it's something to do with my use of the Win32API itself.
Not sure whether the problem is any of these:
- do the integers (3, 0, ...) need to be packed?
- do I need to distinguish between short and long types?
- am I not properly handling the return value?
- if the return value is a pointer, how do I use this in Ruby?
- something else?
Any insight would be much appreciated!