Author Topic: iCALL  (Read 24022 times)

JRS

  • Guest
Re: iCALL
« Reply #15 on: November 30, 2010, 02:03:48 PM »
Quote
I wonder what would be a better name for GTK-server, as it can also 'serve' other libraries...

I view GTK-Server as an interpretive CALL interface. What makes GTK-Server so cool is that you can use the server as a shared object, embedded library, TCP/UDP, FIFO and named pipes to access external interfaces. If I create a interface definition for GTK-Server, that definition can be re-used by any other language. Just like Glade/Builder GUI definitions.

A few names to consider:

iCALL
ScriptOjects
DLL-Server
...

I think that if we could create a .h to .cfg converter to do most of the work, that would make the interface more attractive.

Your one call wonder interface to the system is just amazing!
« Last Edit: November 30, 2010, 02:19:24 PM by JRS »

AIR

  • Guest
Re: iCALL
« Reply #16 on: November 30, 2010, 03:55:07 PM »
Quote
I think that if we could create a .h to .cfg converter to do most of the work, that would make the interface more attractive.

Isn't text processing one of Scriptbasic's strengths? (hint: Get crackin', Son!!!)  ;D ;D ;D

A.

JRS

  • Guest
Re: iCALL
« Reply #17 on: November 30, 2010, 04:13:40 PM »
Already working on a utility in SB. I'm going to convert the complete curses.h file as my test. I'm hoping Peter will chime in and say. "Been there done that ..."

I hope I will have a better understanding of the following when it is complete.

  • Type conversions and keyword options
  • Dynamic call limitations working with shared objects
  • Working with shared object system variables & constants (are they accessible ?)
  • Macro definitions and executing them as casted arguments. (noticed that there are both macro and direct call versions in curses.h)
« Last Edit: November 30, 2010, 05:04:03 PM by JRS »

Pjot

  • Guest
Re: iCALL
« Reply #18 on: November 30, 2010, 11:32:19 PM »
Quote
I'm hoping Peter will chime in and say. "Been there done that ..."

Well, been there done that indeed, but only for the GTK libraries. To create a generic .h to .cfg converter will be very hard as each .h file has its own way of denoting...  :-\

Attached an AWK script which worked for GTK / GDK 2.10. You can also find this in the source distribution of GTK-server. Use the resulting configfile at your own risk!

Regards

JRS

  • Guest
Re: iCALL
« Reply #19 on: November 30, 2010, 11:38:20 PM »
Thanks Peter for the script. As you say, Gtk specific. A good parsing example to learn from though.

I find it easier to copy / paste the extern NCURSES_EXPORT( lines that I want and run the converter on that to generate the .cfg. It's not totally automated but writing a translator is much easier and I'm only dealing with what matters. I will more than likely generate a [module_name].cfg and a [module_name].def that will contain definitions you paste in your program.
« Last Edit: December 01, 2010, 02:41:01 AM by JRS »

JRS

  • Guest
Re: iCALL
« Reply #20 on: December 01, 2010, 11:18:01 PM »
I'm not sure at this point how many shared object libraries are a good candidate for interpretive/dynamic function calls. I'm going to hand assemble a few variations of .h files first before considering a translator effort. I'm going to write a utility that will parse DLL() functions in a script that is currently using the .cfg option for definitions and generate a gtk-server-define list by converting the definitions from the .cfg file that were used in the program eliminating the need for the .cfg file. I will still need to test each function and maybe create a demo program touching on the main functionality of using curses in your scripts.
« Last Edit: December 02, 2010, 12:09:25 AM by JRS »

JRS

  • Guest
Re: iCALL
« Reply #21 on: December 02, 2010, 12:19:54 AM »
ScriptBasic doesn't currently have a SQLite extension module. (MySQL, PostgreSQL, iODBC, Berleley DB modules only at this time)

It might be a good test of the GTK-Server interface to see if it is robust enough to support DB access.

Post your SQLite GTK-Server definitions here if you wish to help. (sqlite.h to sqlite.cfg)

The following is a SQLite example done in BaCon which is close in syntax to ScriptBasic and Peter wrote GTK-Server as well.

Code: Text
  1. '
  2. ' Simple SQLite3 wrapper - PvE May 2010, GPL.
  3. '
  4. ' SQL syntax here: http://www.sqlite.org/lang.html
  5. '
  6. ' Version 1.0: initial release
  7. ' Version 1.1: fixed compile warning in DB_ERR$
  8. '---------------------------------------------------------------------------------------------------------
  9.  
  10. TRAP LOCAL
  11. CATCH GOTO sqlite_handle_error
  12.  
  13. sqlite_LIB$ = "libsqlite3.so"
  14. sqlite_seq = -1
  15.  
  16. LABEL sqlite_import_retry
  17.     INCR sqlite_seq
  18.     sqlite_retry = FALSE
  19.     IMPORT "sqlite3_open(char*,long)" FROM sqlite_LIB$ TYPE int
  20.     IF sqlite_retry THEN GOTO sqlite_import_retry
  21.  
  22. GOTO sqlite_continue
  23.  
  24. LABEL sqlite_handle_error
  25.     IF sqlite_seq IS 0 THEN sqlite_LIB$ = "libsqlite3.so.0"
  26.     ELSE sqlite_LIB$ = CONCAT$(LEFT$(sqlite_LIB$, INSTRREV(sqlite_LIB$, ".")), STR$(sqlite_seq))
  27.     IF sqlite_seq < 10 THEN sqlite_retry = TRUE
  28.     ELSE
  29.         PRINT "No SQLite library found!"
  30.         END
  31.     END IF
  32.     RESUME
  33.  
  34. LABEL sqlite_continue
  35.  
  36. IMPORT "sqlite3_close(long)" FROM sqlite_LIB$ TYPE int
  37. IMPORT "sqlite3_errmsg(long)" FROM sqlite_LIB$ TYPE char*
  38. IMPORT "sqlite3_exec(long,char*,void*,void*,long)" FROM sqlite_LIB$ TYPE int
  39. IMPORT "sqlite3_free(void*)" FROM sqlite_LIB$ TYPE void
  40. IMPORT "sqlite3_libversion(void)" FROM sqlite_LIB$ TYPE char*
  41.  
  42. DECLARE DB_FS$, DB_RS$, DB_RESULT$, DB_ERROR$
  43. DECLARE sqlite_internal_flag
  44.  
  45. CONST SQLITE_OK = 0
  46.  
  47. DB_FS$ = TAB$(1)
  48. DB_RS$ = NL$
  49.  
  50. '---------------------------------------------------------------------------------------------------------
  51.  
  52. FUNCTION DB_OPEN(STRING name)
  53.  
  54.     LOCAL db, result
  55.  
  56.     result = sqlite3_open(name, ADDRESS(db))
  57.  
  58.     IF result THEN RETURN result
  59.  
  60.     RETURN db
  61.  
  62. END FUNCTION
  63.  
  64. '---------------------------------------------------------------------------------------------------------
  65.  
  66. FUNCTION sqlite_results(void *NotUsed, int amount, char **value, char **column_name)
  67.  
  68.     LOCAL i
  69.  
  70.     IF sqlite_internal_flag AND amount > 0 THEN
  71.         DB_RESULT$ = ""
  72.         FOR i = 0 TO amount - 1
  73.             DB_RESULT$ = CONCAT$(DB_RESULT$, column_name[i], DB_FS$)
  74.         NEXT
  75.         DB_RESULT$ = CONCAT$(DB_RESULT$, DB_RS$)
  76.         sqlite_internal_flag = FALSE
  77.     ENDIF
  78.  
  79.     IF amount > 0 THEN
  80.         FOR i = 0 TO amount - 1
  81.             DB_RESULT$ = CONCAT$(DB_RESULT$, value[i], DB_FS$)
  82.         NEXT
  83.         DB_RESULT$ = CONCAT$(DB_RESULT$, DB_RS$)
  84.     END IF
  85.  
  86.     RETURN 0
  87.  
  88. END FUNCTION
  89.  
  90. '---------------------------------------------------------------------------------------------------------
  91.  
  92. FUNCTION DB_SQL(NUMBER db, STRING sql$)
  93.  
  94.     LOCAL result TYPE int
  95.     LOCAL err_msg TYPE char*
  96.  
  97.     DB_ERROR$ = ""
  98.     sqlite_internal_flag = TRUE
  99.     result = sqlite3_exec(db, sql$, sqlite_results, 0, ADDRESS(err_msg))
  100.  
  101.     IF result NE SQLITE_OK THEN
  102.         DB_ERROR$ = err_msg
  103.         sqlite3_free(err_msg)
  104.     END IF
  105.  
  106.     RETURN result
  107.  
  108. END FUNCTION
  109.  
  110. '---------------------------------------------------------------------------------------------------------
  111.  
  112. FUNCTION DB_CLOSE(NUMBER db)
  113.  
  114.     LOCAL result TYPE int
  115.  
  116.     result = sqlite3_close(db)
  117.  
  118.     RETURN result
  119.  
  120. END FUNCTION
  121.  
  122. '---------------------------------------------------------------------------------------------------------
  123.  
  124. FUNCTION DB_STATUS$(NUMBER db)
  125.  
  126.     LOCAL status$
  127.  
  128.     status$ = sqlite3_errmsg(db)
  129.  
  130.     RETURN status$
  131.  
  132. END FUNCTION
  133.  
  134. '---------------------------------------------------------------------------------------------------------
  135.  
  136. FUNCTION DB_VERSION$()
  137.  
  138.     LOCAL version$
  139.  
  140.     version$ = sqlite3_libversion()
  141.  
  142.     RETURN version$
  143.  
  144. END FUNCTION
  145.  
  146. '---------------------------------------------------------------------------------------------------------
  147.  
  148. TRAP SYSTEM
  149. CATCH RESET
  150.  

FUNCTIONS:
----------
DB_OPEN("dbname")
    Opens database, if succeeds it returns a handle to database, else returns DB statuscode

DB_SQL("sql string")
    Executes SQL command, returns DB statuscode, SQL results stored in DB_RESULT$, SQL error messages stored in DB_ERROR$

DB_CLOSE(db)
    Closes database, returns DB statuscode

DB_STATUS$(db)
    If a returned DB status code is higher than 0, this function returns the status in human readable format

DB_VERSION$()
    Returns verion string of SQLite


VARIABLES:
----------
DB_FS$
    Field Separator for the results in DB_RESULT$, defaults to tab, can be set to any other string by user

DB_RS$
    Record Separator for the results in DB_RESULT$, defaults to newline, can be set to any other string by user

DB_RESULT$
    Contains last result of SQL command executed by 'DB_SQL'

DB_ERROR$
    Contains last error string of SQL command executed by 'DB_SQL'


SQLITE SQL syntax here: http://www.sqlite.org/lang.html

Code: Text
  1. '
  2. ' Demonstration program for SQlite3
  3. '
  4. ' PvE - May 2010, GPL.
  5. ' ------------------------------------------------------------------------
  6.  
  7. ' Include the binding
  8. INCLUDE "sqlite3.bac"
  9.  
  10. ' Name of the data file
  11. CONST datafile$ = "data.sdb"
  12.  
  13. ' Print version
  14. PRINT NL$, "Using SQLite version: ", DB_VERSION$()
  15.  
  16. ' Create a database
  17. mydb = DB_OPEN(datafile$)
  18.  
  19. ' Create table and add data
  20. DB_SQL(mydb, "CREATE TABLE demo(someval INTEGER,  sometxt TEXT);")
  21. DB_SQL(mydb, "INSERT INTO demo VALUES (123, 'Hello');")
  22. DB_SQL(mydb, "INSERT INTO demo VALUES (234, 'cruel');")
  23. DB_SQL(mydb, "INSERT INTO demo VALUES (345, 'world');")
  24. DB_SQL(mydb, "COMMIT;")
  25.  
  26. ' Fetch some data
  27. res = DB_SQL(mydb, "SELECT * FROM demo;")
  28. IF res IS 0 THEN PRINT NL$, DB_RESULT$
  29. ELSE PRINT NL$, DB_ERROR$
  30.  
  31. ' Count the records
  32. DB_SQL(mydb, "SELECT COUNT(*) FROM demo;")
  33. PRINT "Amount of records: ", MID$(DB_RESULT$, INSTR(DB_RESULT$, NL$) + 1)
  34.  
  35. ' Close database
  36. res = DB_CLOSE(mydb)
  37.  
  38. ' Print some info
  39. PRINT "Size of data file is: ", FILELEN(datafile$), " bytes.", NL$
  40.  
  41. ' Delete data file again
  42. DELETE FILE datafile$
  43.  
« Last Edit: December 02, 2010, 12:39:17 AM by JRS »

JRS

  • Guest
Re: iCALL
« Reply #22 on: December 02, 2010, 04:18:29 PM »
I wasn't able to get past the OPEN for SQLite3. (seg fault)

It looks like the sqlite3_open function is asking for a pointer to a LONG variable defined in your program. SB doesn't have a VARPTR like function in the language.

Any ideas as a work around or function in GTK-Server to deal with this?

I noticed a few glib definitions at the end of the gtk-server.cfg and was wondering if maybe I could call one of these low level functions to get a pointer to a variable.

I could always create a helper extension module for SB to deal with issue like the above. Extension module give full access to the SB & OS API at a C level and can return in a SB variable the required results.

Code: [Select]
SQLITE_API int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */

Quote from: sqlite3.h
These routines open an SQLite database file whose name is given by the
filename argument. The filename argument is interpreted as UTF-8 for
sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
order for sqlite3_open16(). (A [database connection] handle is usually
returned in *ppDb, even if an error occurs.  The only exception is that
if SQLite is unable to allocate memory to hold the [sqlite3] object,
a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
object.) (If the database is opened (and/or created) successfully, then
[SQLITE_OK] is returned.  Otherwise an [error code] is returned.) The
[sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain
an English language description of the error following a failure of any
of the sqlite3_open() routines.

« Last Edit: December 02, 2010, 09:38:07 PM by JRS »

JRS

  • Guest
Re: iCALL
« Reply #23 on: December 03, 2010, 11:24:45 AM »
It looks like there isn't a easy quick fix for this issue based on the lack of response.

Unless I hear something soon, I'm going to add a VARPTR() function to gtk-server.so (SB specific version) to return a numeric value of the address of where the variable is stored. This problem has come up before and one of the reasons Peter said I was going to have issues with the GNOME-DB interface and trying to use GTK-SERVER to access it.


JRS

  • Guest
Re: iCALL
« Reply #24 on: December 03, 2010, 09:03:17 PM »
I was browsing through the GTK-Server source to add a VARPTR() function to the ScriptBasic specific version of the shared object library. The GTK-Server extension module is as thin as you can get and still call it an extension module.

Code: [Select]
esVERSION_NEGOTIATE
    return (int)INTERFACE_VERSION;
besEND

besSUB_START

besEND

besSUB_FINISH

besEND

besFUNCTION(_gtk)
    VARIABLE ptr;
    char* arg0;
    char* retstr;

    if(besARGNR>1) return EX_ERROR_TOO_MANY_ARGUMENTS;
    if(besARGNR<1) return EX_ERROR_TOO_FEW_ARGUMENTS;

    ptr = besARGUMENT(1);
    besDEREFERENCE(ptr);
    arg0 = besCONVERT2ZCHAR(besCONVERT2STRING(ptr),arg0);

    retstr = (char*)gtk(arg0);

    besALLOC_RETURN_STRING(strlen(retstr));
    memcpy(STRINGVALUE(besRETURNVALUE),retstr,strlen(retstr));

    besFREE(arg0);
besEND

/* Needed to compile standalone Scriptbasic programs */
SLFST VISIO_SLFST[] = {

    {"versmodu", versmodu},
    {"bootmodu", bootmodu},
    {"finimodu", finimodu},
    {"_gtk", _gtk},
    {NULL, NULL}
};

This is the most logical place to add the missing access to low level (C) functionality that shared objects require but aren't available to the user at the script level. The _gtk function does what I need except it doesn't allow me to pass it a SB variable and return the pointer as a numeric value. The new VARPTR function should only take a few lines of code and never have to call any standard GTK-Server internal functions.
« Last Edit: December 03, 2010, 09:05:22 PM by JRS »

JRS

  • Guest
Re: iCALL
« Reply #25 on: December 03, 2010, 10:09:09 PM »
This is my guess at what is needed. The theory is that if I want to pass SQLite3_Open() a pointer to a long, I call GTK-Server's new varptr function passing a 4 byte string constant. (if you don't care what it gets populated with) The alternative is to pass a 4 byte 'string' variable (a="    ") then you should be able to reference a and it return it's post function call value. Before I try this, any feedback from Armando or Peter would be appreciated.

Code: [Select]
esVERSION_NEGOTIATE
    return (int)INTERFACE_VERSION;
besEND

besSUB_START

besEND

besSUB_FINISH

besEND

besFUNCTION(_gtk)
    VARIABLE ptr;
    char* arg0;
    char* retstr;

    if(besARGNR>1) return EX_ERROR_TOO_MANY_ARGUMENTS;
    if(besARGNR<1) return EX_ERROR_TOO_FEW_ARGUMENTS;

    ptr = besARGUMENT(1);
    besDEREFERENCE(ptr);
    arg0 = besCONVERT2ZCHAR(besCONVERT2STRING(ptr),arg0);

    retstr = (char*)gtk(arg0);

    besALLOC_RETURN_STRING(strlen(retstr));
    memcpy(STRINGVALUE(besRETURNVALUE),retstr,strlen(retstr));

    besFREE(arg0);
besEND

besFUNCTION(varptr)
    VARIABLE ptr;
    char* arg0;
    char* retstr;

    if(besARGNR>1) return EX_ERROR_TOO_MANY_ARGUMENTS;
    if(besARGNR<1) return EX_ERROR_TOO_FEW_ARGUMENTS;

    ptr = besARGUMENT(1);
    besDEREFERENCE(ptr);
    retstr = besCONVERT2ZCHAR(besCONVERT2STRING(ptr),arg0);

    besALLOC_RETURN_STRING(strlen(retstr));
    memcpy(STRINGVALUE(besRETURNVALUE),retstr,strlen(retstr));

    besFREE(arg0);
besEND


/* Needed to compile standalone Scriptbasic programs */
SLFST VISIO_SLFST[] = {

    {"versmodu", versmodu},
    {"bootmodu", bootmodu},
    {"finimodu", finimodu},
    {"_gtk", _gtk},
    {"varptr","varptr"},
    {NULL, NULL}
};
« Last Edit: December 03, 2010, 11:10:01 PM by JRS »

AIR

  • Guest
Re: iCALL
« Reply #26 on: December 04, 2010, 08:55:06 AM »
This is not tested, but I would try something like:

Code: [Select]
besFUNCTION(varptr)
  VARIABLE ptr;

  if(besARGNR>1) return EX_ERROR_TOO_MANY_ARGUMENTS;
  if(besARGNR<1) return EX_ERROR_TOO_FEW_ARGUMENTS;

  besALLOC_RETURN_LONG
 
  ptr = besARGUMENT(1);
  besDEREFERENCE(ptr);
 
  LONGVALUE(besRETURNVALUE) = (int)ptr;

besEND

The upshot is you need to return the ADDRESS of the db object.

A.

JRS

  • Guest
Re: iCALL
« Reply #27 on: December 04, 2010, 09:57:13 AM »
Thanks Armando!

I'll give this a try today and see if I can move the iCALL effort along.

Will this work no matter what the variable I pass contains? (number, string, float)
« Last Edit: December 04, 2010, 10:13:44 AM by JRS »

JRS

  • Guest
Re: iCALL
« Reply #28 on: December 04, 2010, 10:58:06 AM »
I compiled a new gtk-server.so for ScriptBasic but noticed some warnings during the make.

Code: [Select]
root@Laptop:/usr/src/gtk-server-2.3.1-sr# make
rm -f libgtk-server.so *.a *.o *.log so_locations
gcc -Wall -pedantic -pthread -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12   -I/usr/src/scriptbasic/  -DHAVE_CONFIG_H -DLOCALCFG=\"/etc/gtk-server.cfg\"   -c -o gtk-server.o gtk-server.c
gtk-server.c: In function ‘bootmodu’:
gtk-server.c:6090: warning: unused variable ‘pEo’
gtk-server.c: In function ‘finimodu’:
gtk-server.c:6094: warning: unused variable ‘pEo’
gtk-server.c: In function ‘_gtk’:
gtk-server.c:6108: warning: operation on ‘arg0’ may be undefined
gtk-server.c:6098: warning: unused variable ‘pEo’
gtk-server.c: In function ‘varptr’:
gtk-server.c:6119: warning: unused variable ‘pEo’
gtk-server.c: At top level:
gtk-server.c:6137: warning: ISO C forbids initialization between function pointer and ‘void *’
gtk-server.c:6138: warning: ISO C forbids initialization between function pointer and ‘void *’
gtk-server.c:6139: warning: ISO C forbids initialization between function pointer and ‘void *’
gtk-server.c:6140: warning: ISO C forbids initialization between function pointer and ‘void *’
gtk-server.c:6141: warning: ISO C forbids initialization between function pointer and ‘void *’
gcc -o libgtk-server.so gtk-server.o  -export-dynamic  -lffi -pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lm -lcairo -lpng12 -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lglib-2.0   -shared
strip libgtk-server.so
ar -r libgtk-server.a gtk-server.o
ar: creating libgtk-server.a
ranlib libgtk-server.a
root@Laptop:/usr/src/gtk-server-2.3.1-sr#

Here is my ScriptBasic VARPTR() test program.

Code: [Select]
DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server"

mylong = 0

ptr = VARPTR(mylong)

PRINT ptr,"\n"

And the results ...

jrs@Laptop:~/SB/test$ scriba testvarptr.sb
167558396
jrs@Laptop:~/SB/test$

AIR

  • Guest
Re: iCALL
« Reply #29 on: December 04, 2010, 11:32:04 AM »
Quote
gtk-server.c: In function ‘bootmodu’:
gtk-server.c:6090: warning: unused variable ‘pEo’
gtk-server.c: In function ‘finimodu’:
gtk-server.c:6094: warning: unused variable ‘pEo’
gtk-server.c: In function ‘_gtk’:
gtk-server.c:6108: warning: operation on ‘arg0’ may be undefined
gtk-server.c:6098: warning: unused variable ‘pEo’
gtk-server.c: In function ‘varptr’:
gtk-server.c:6119: warning: unused variable ‘pEo’
Quote
gcc -Wall -pedantic

That's why you see these warnings.

Quote
warning: ISO C forbids initialization between function pointer and ‘void *’

You need to cast to return the correct type, I believe. 

A.