BASIC Developer & Support Resources > Scripting Languages

IDLL

(1/8) > >>

JRS:
I added a couple more wrapper functions to the gtk-server.so extension module. These two functions prefix what the user passes for IUSE and IDECLARE. ("gtk_server_require " and "gtk_server_define ") internally. I added them to make the .sbh files more readable and getting use to making changes to the gtk-server library.

Depending on your style of coding, the IUSE and IDECLARE can be anywhere in your program. (as long as you only call it once and before use)

[*]GTK-Server
[*]GTK-Server Manual
[*]GTK-Server Tutorial
[*]GTK-Server Configuration
[*]gtk-server.cfg
[*]GTK-Server.org
[/list]




--- Code: Text ---' INTERFACEDECLARE SUB IDLL ALIAS "_gtk" LIB "gtk-server"DECLARE SUB IUSE ALIAS "_gtk_require" LIB "gtk-server"DECLARE SUB IDECLARE ALIAS "_gtk_define" LIB "gtk-server"DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server" ' GDA4IUSE("libgda-4.0.so")IUSE("libgda-ui-4.0.so") ' DECLARE IDECLARE("gtk_init NONE NONE 2 NULL NULL")IDECLARE("gtk_dialog_new_with_buttons NONE WIDGET 8 STRING WIDGET INT STRING INT STRING INT NULL")IDECLARE("gdaui_login_new NONE WIDGET 1 STRING")IDECLARE("gtk_box_pack_start NONE NONE 5 WIDGET WIDGET BOOL BOOL INT")IDECLARE("gtk_dialog_get_content_area NONE WIDGET 1 WIDGET")IDECLARE("gtk_widget_show NONE NONE 1 WIDGET")IDECLARE("gtk_dialog_run delete-event INT 1 WIDGET")IDECLARE("gdaui_login_get_connection_information NONE WIDGET 1 WIDGET")IDECLARE("gda_connection_open_from_string NONE WIDGET 5 STRING STRING POINTER INT NULL")IDECLARE("gtk_widget_destroy NONE NONE 1 WIDGET")IDECLARE("gda_execute_select_command NONE WIDGET 3 WIDGET STRING NULL")IDECLARE("g_object_unref NONE NONE 1 WIDGET")IDECLARE("gtk_window_new delete-event WIDGET 1 INT")IDECLARE("gdaui_grid_new NONE WIDGET 1 WIDGET")IDECLARE("gtk_container_add NONE NONE 2 WIDGET WIDGET")IDECLARE("gtk_widget_show_all NONE NONE 1 WIDGET")IDECLARE("gtk_server_callback NONE STRING 1 STRING")IDECLARE("gtk_window_set_default_size NONE NONE 3 WIDGET INT INT")IDECLARE("gtk_window_set_title NONE NONE 2 WIDGET STRING")IDECLARE("strncpy NONE STRING 3 POINTER POINTER INT")IDECLARE("strdup NONE STRING 1 POINTER")  CONST GTK_STOCK_CANCEL = "gtk-cancel"CONST GTK_STOCK_OK = "gtk-ok"CONST GTK_RESPONSE_NONE = -1CONST GTK_RESPONSE_OK = -5CONST GDA_CONNECTION_OPTIONS_NONE = 0CONST GTK_WINDOW_TOPLEVEL = 0CONST GTK_DIALOG_MODAL = 1CONST provider = 4CONST cnc_string = 12   FUNCTION STRPTR(pointer)LOCAL info_str info_str = 0IDLL("strncpy " & VARPTR(info_str) & " " & pointer & " 4")STRPTR = IDLL("strdup " & info_str) END FUNCTION  SUB gtk_mainLOCAL event REPEAT  event = IDLL("gtk_server_callback wait")UNTIL event = window END SUB 
The GNOME-DB-GRID code challenge main program.


--- Code: Text ---' GNOME-DB GRID  INCLUDE "gnome-db.sbh" IDLL("gtk_init 0 0")IDLL("gdaui_init") ' DB Control Windowwindow = IDLL("gtk_dialog_new_with_buttons \"Select the Data Source to connect to\" 0 " & GTK_DIALOG_MODAL & " " & GTK_STOCK_CANCEL & " " & GTK_RESPONSE_NONE & " " & GTK_STOCK_OK & " " & GTK_RESPONSE_OK & " 0")login = IDLL("gdaui_login_new NULL")IDLL("gtk_box_pack_start " & IDLL("gtk_dialog_get_content_area " & window) & " " &  login & " TRUE TRUE 0")IDLL("gtk_widget_show " & login)IF IDLL("gtk_dialog_run " & window) <> GTK_RESPONSE_OK THEN  PRINT "Cancelled!\n"  ENDEND IFdsninfo = IDLL("gdaui_login_get_connection_information " & login)cnc = IDLL("gda_connection_open_from_string " & STRPTR(dsninfo + provider) & " " & STRPTR(dsninfo + cnc_string) & " " & " 0 0 0")data_model = IDLL("gda_execute_select_command " & cnc & " \"SELECT * FROM customers\" 0")IDLL("gtk_widget_destroy " & window) ' DB Data Gridwindow = IDLL("gtk_window_new 0")IDLL("gtk_window_set_title " & window & " \"GNOME-DB Grid Control Example\"")IDLL("gtk_window_set_default_size " & window & " 400 200")grid = IDLL("gdaui_grid_new " & data_model)IDLL("g_object_unref " & data_model)IDLL("gtk_container_add " & window & " " & grid)IDLL("gtk_widget_show_all " & window) gtk_main() IDLL("g_object_unref " & cnc) 
GNOME-DB-GRID sample.c
GNOME-DB GdaBrowser

Current ScriptBasic version of the gtk-server.c code modified for this demo. I would think these changes would work with the Windows and Mac versions of GTK-Server. (SB version)


--- Code: ---#ifdef GTK_SERVER_SCRIPTBASIC
besVERSION_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(_gtk_require)
    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);

    #define GTKSRV_REQUIRE "gtk_server_require "

    arg0 = besCONVERT2ZCHAR(besCONVERT2STRING(strcat(GTKSRV_REQUIRE,STRINGVALUE(ptr))),arg0);

    retstr = (char*)gtk(arg0);

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

    besFREE(arg0);
besEND

 
besFUNCTION(_gtk_define)
    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);

    #define GTKSRV_DEFINE "gtk_server_define "

    arg0 = besCONVERT2ZCHAR(besCONVERT2STRING(strcat(GTKSRV_DEFINE,STRINGVALUE(ptr))),arg0);

    retstr = (char*)gtk(arg0);

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

    besFREE(arg0);
besEND


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


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

    {"versmodu", versmodu},
    {"bootmodu", bootmodu},
    {"finimodu", finimodu},
    {"_gtk", _gtk},
    {"_gtk_require",_gtk_require},
    {"_gtk_define",_gtk_define},
    {"varptr",varptr},
    {NULL, NULL}
};

#endif /* End of ScriptBasic code */

--- End code ---

JRS:
If you prefer more of a traditional function calling method rather then using a single string, I added a DLL (function CALL interface to IDLL) just for you.  :)


--- Code: ---' INTERFACE
DECLARE SUB IDLL ALIAS "_gtk" LIB "gtk-server"
DECLARE SUB IUSE ALIAS "_gtk_require" LIB "gtk-server"
DECLARE SUB IDECLARE ALIAS "_gtk_define" LIB "gtk-server"
DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server"

' GDA4
IUSE("libgda-4.0.so")
IUSE("libgda-ui-4.0.so")

' DECLARE

IDECLARE("gtk_init NONE NONE 2 NULL NULL")
IDECLARE("gtk_dialog_new_with_buttons NONE WIDGET 8 STRING WIDGET INT STRING INT STRING INT NULL")
IDECLARE("gdaui_login_new NONE WIDGET 1 STRING")
IDECLARE("gtk_box_pack_start NONE NONE 5 WIDGET WIDGET BOOL BOOL INT")
IDECLARE("gtk_dialog_get_content_area NONE WIDGET 1 WIDGET")
IDECLARE("gtk_widget_show NONE NONE 1 WIDGET")
IDECLARE("gtk_dialog_run delete-event INT 1 WIDGET")
IDECLARE("gdaui_login_get_connection_information NONE WIDGET 1 WIDGET")
IDECLARE("gda_connection_open_from_string NONE WIDGET 5 STRING STRING POINTER INT NULL")
IDECLARE("gtk_widget_destroy NONE NONE 1 WIDGET")
IDECLARE("gda_execute_select_command NONE WIDGET 3 WIDGET STRING NULL")
IDECLARE("g_object_unref NONE NONE 1 WIDGET")
IDECLARE("gtk_window_new delete-event WIDGET 1 INT")
IDECLARE("gdaui_grid_new NONE WIDGET 1 WIDGET")
IDECLARE("gtk_container_add NONE NONE 2 WIDGET WIDGET")
IDECLARE("gtk_widget_show_all NONE NONE 1 WIDGET")
IDECLARE("gtk_server_callback NONE STRING 1 STRING")
IDECLARE("gtk_window_set_default_size NONE NONE 3 WIDGET INT INT")
IDECLARE("gtk_window_set_title NONE NONE 2 WIDGET STRING")
IDECLARE("strncpy NONE STRING 3 POINTER POINTER INT")
IDECLARE("strdup NONE STRING 1 POINTER")


CONST GTK_STOCK_CANCEL = "gtk-cancel"
CONST GTK_STOCK_OK = "gtk-ok"
CONST GTK_RESPONSE_NONE = -1
CONST GTK_RESPONSE_OK = -5
CONST GDA_CONNECTION_OPTIONS_NONE = 0
CONST GTK_WINDOW_TOPLEVEL = 0
CONST GTK_DIALOG_MODAL = 1
CONST provider = 4
CONST cnc_string = 12


FUNCTION DLL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
LOCAL arg_str
  arg_str = STR(a0) & " " & STR(a1) & " " & STR(a2) & " " & STR(a3) & " " & STR(a4) & " " & STR(a5) & " " & STR(a6) & " " & STR(a7) & " " & STR(a8) & " " & STR(a9)
  DLL = IDLL(arg_str)
END FUNCTION


FUNCTION STRPTR(pointer)
LOCAL info_str

info_str = 0
IDLL("strncpy " & VARPTR(info_str) & " " & pointer & " 4")
STRPTR = IDLL("strdup " & info_str)

END FUNCTION


SUB gtk_main
LOCAL event

REPEAT
  event = IDLL("gtk_server_callback wait")
UNTIL event = window

END SUB

--- End code ---

Nothing else was changed in the gnome-db.sbh include file. Notice the difference between this version of gda.sb using DLL and the previous version using IDLL.


--- Code: Text ---' GNOME-DB GRID  INCLUDE "gnome-db.sbh" DLL("gtk_init", 0, 0)DLL("gdaui_init") ' DB Control Windowwindow = DLL("gtk_dialog_new_with_buttons","Select the Data Source to connect to", 0, GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_OK, GTK_RESPONSE_OK, 0)login = DLL("gdaui_login_new", NULL)DLL("gtk_box_pack_start", DLL("gtk_dialog_get_content_area", window), login, TRUE, TRUE, 0)DLL("gtk_widget_show", login)IF DLL("gtk_dialog_run", window) <> GTK_RESPONSE_OK THEN  PRINT "Cancelled!\n"  ENDEND IFdsninfo = DLL("gdaui_login_get_connection_information", login)cnc = DLL("gda_connection_open_from_string", STRPTR(dsninfo + provider), STRPTR(dsninfo + cnc_string), 0, 0, 0)data_model = DLL("gda_execute_select_command", cnc, "SELECT * FROM customers", 0)DLL(gtk_widget_destroy, window) ' DB Data Gridwindow = DLL("gtk_window_new", 0)DLL("gtk_window_set_title", window, "GNOME-DB Grid Control Example")DLL("gtk_window_set_default_size", window, 400, 200)grid = DLL("gdaui_grid_new", data_model)DLL("g_object_unref", data_model)DLL("gtk_container_add", window, grid)DLL("gtk_widget_show_all", window) gtk_main() DLL("g_object_unref", cnc) 

AIR:

--- Quote ---IDECLARE("strdup NONE STRING 1 POINTER")
--- End quote ---

strdup calls malloc() to create the copy of the string.

Wouldn't that potentially cause an issue on long running programs, because the copy is never "free()" 'd?

JRS:
My understanding of how SB manages memory is that it releases all memory used after scriba ends. Keep in mind that I'm calling strdup() via GTK-Server which is a SB extension module following the SB memory allocation guidelines established.

Maybe Peter Verhas can address this in a better way.

AIR:
Yes, but normally sb handles the memory allocation.  Perhaps gtk-server does as well, but I don't know.  However, calling strdup falls outside of that.  It's like calling malloc/calloc directly within a module.

For short demo programs this is not really an issue.  For long running apps it could be an issue at some point.

Is it possible to run valgrind against a running sb script (actually against scriba)?  If you have leaks, that's one way to discover where they're coming from....

Navigation

[0] Message Index

[#] Next page

Go to full version