A DL-Ruby Question

K

Kevin Proctor

I first found out about the Ruby/DL library on WhyTheLuckyStiff.net in
an article on 1.8 ->
http://whytheluckystiff.net/articles/2003/08/04/rubyOneEightOh It's a
great article and I really liked the idea of using DL to make a pure
ruby extension type deal.

I immediately decided to try to jam it and the SQLite library
(www.sqlite.org) together. Please note - this is my first shot at it,
and I have been drinking and watching LOTR at the same time. So if
there's something really obviously wrong or silly here - that's my
excuse. :) That and I had some trouble finding docs for it - but that's
quite possibly my being impatient and wanting to just jump right in.

First I look at the simplest possible version of the SQLite interface.

# typedef struct sqlite sqlite;
# sqlite *sqlite_open(const char *dbname, int mode, char **errmsg);
# int sqlite_exec(
# sqlite *db,
# char *sql,
# int (*xCallback)(void*,int,char**,char**),
# void *pArg,
# char **errmsg
# );
# void sqlite_close(sqlite *db);

So I start off with this in Ruby (less some unimportant stuff)

SqliteStruct = struct []
extern "void *sqlite_open(char*, int, char **)"
extern "void sqlite_close(void*)"
extern "int sqlite_exec(void*, char*, int, void*, char **)"

Now I'm ready to play with my Ruby SQLite interface

dB = Sqlite::SqliteStruct.new(Sqlite.sqlite_open( "temp.db", 0, errMsg))

Sqlite.sqlite_exec(dB, "create table tbl1(one varchar(10), two
smallint)", 0, nil, nil)
Sqlite.sqlite_exec(dB, "insert into tbl1 values('hello!',10)",0, nil, nil)
Sqlite.sqlite_exec(dB, "insert into tbl1 values('goodbye', 20)", 0, nil,
nil)
foo = Sqlite.sqlite_exec(dB, "select * from tbl1", 0, nil, nil)

Sqlite.sqlite_close(dB);

This sucessfully creates the database, puts some stuff in it and then
closes it.

But, and there's always a but, you may have noticed the ugliness in my
sqlite_exec function. I'm just passing an int (0 specifically) - I
really want to put a 'function pointer' there to do neat things with the
results of my sql statement. For the life of me I can not find an
example of doing something like this in DL. I'm sure it's there
somewhere but I'm stumped.

I've decided to ask here if you can see where I've gone wrong. :)
And to ask if anyone out there has any nead Ruby/DL projects they've
completed.

Kevin
 
R

Robert Feldt

Kevin Proctor said:
But, and there's always a but, you may have noticed the ugliness in my sqlite_exec function. I'm just passing an int (0 specifically) - I really want to put a 'function pointer' there to do neat things with the results of my sql statement. For the life of me I can not find an example of doing something like this in DL. I'm sure it's there somewhere but I'm stumped.
If you're trying to do a callback to Ruby from C then this example
might help you:

# Example 7. Calling back to a Ruby function from a C function
#
# Sometimes C code takes a function as a parameter and calls that function.
# To be able to use such C code from Ruby we need to be able to call back
# from C to Ruby and transfer parameters and results back and forth.
# Here's a simple example to show how this can be done.
#
require 'example_runner'

cf = CFile.new "ex1.c", <<EOC

#include <stdio.h>

/* CompareStringLengths is a pointer to a function comparing the length
* of two strings and returning -1, 0, or 1 */
typedef int (*CompareStringLengths)(char *str1, char *str2);

extern void report_string_compare(char *str1, char *str2, CompareStringLengths compare_func) {
int result = (*compare_func)(str1, str2);

printf("Results was %d.\\n", result);
}
EOC

cf.compile_to_dll_with_command "gcc -shared -o test.so"

require 'dl/import'
require 'dl/struct'

module Ex07
extend DL::Importable
dlload './test.so'

def str_len_compare(str1, str2)
puts "Callback succeeded: We are in Ruby from C now!"
str1.length <=> str2.length
end
STRLENCOMPARE = callback "int str_len_compare(char*,char*)"
extern "void report_string_compare(char*, char*, void*)"
end

Ex07.report_string_compare("ab", "cde", Ex07::STRLENCOMPARE)
Ex07.report_string_compare("abc", "d", Ex07::STRLENCOMPARE)
Ex07.report_string_compare("ab", "cd", Ex07::STRLENCOMPARE)


I did a series of such examples and intended to release them but then
I got stuck on the non-portability of nested structs and
didn't go further in my efforts to use dl for a full extension.

The example_runner is just a little class to compile the C code
to a dll; excluded here for brevity.

Regards,

Robert Feldt
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,112
Latest member
BrentonMcc
Top