Digital Workshop

Welcome to the Digital Workshop Message Boards
It is currently December 23rd, 2024, 7:36 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 17 posts ]  Go to page Previous  1, 2
Author Message
 Post subject:
PostPosted: May 8th, 2008, 2:22 am 
Offline
Godlike
Godlike

Joined: November 12th, 2005, 1:56 am
Posts: 1474
Location: SFBay Area
Opus: OpusPro v9.0x, & Evol.
OS: Vista32
System: Core 2 duo 2Ghz, RAM 3GB, Nvidia Go 7700 - laptop
I'm over on another post trying to use a DLL to connect to a DB.
viewtopic.php?p=13703#13703

Some advice I got there, is more general and better fits this thread... as to tools and approaches for non-managed DLL's.

Olaf Schmidt of datenhaus.de writes:
Quote:
As I read somewhat in this forum, it seems you have to call external Dlls always with a "three-param-prefix" before the real Parameter-Pairs are added.

- param 1 is the external function-name
- param2 to define true when the call is involving a GUI-interaction (in your case false) - and param 3 is the type of the Function-return-value.

Then the "normal" Params are added as Pairs:
first the type-description - always given as a string;
and then the other part of the param-pair,
the script-variable, which transports something into the Dll.

Not yet found, how you can tell the Dll-Calling-Mechanism, that a Param is not an [In]-Value (usually the Data behind a variable), but instead an [Out]-Value (which usually is the pointer of the Variable and not its content - used, to let the Dll fill something in into such an "Out-Param-Pointer").

[ Edit -LL ... section deleted]
- - - - - - - - - - - - -
And BTW, no need to install huge .NET-environments, just to compile a small Helper-Dll (and yes, C# is not of much use for Opus, because the C# MSIL-compiler normally generates so called managed Dlls, only usable by .NET-Apps, requiring the appropriate framework preinstalled on a WinSystem.

Please look at e.g. tinycc - a superfast C-Compiler, coming in a 200kByte-Zip-File, able to compile small Std-Dlls, defined in plain C, why not use that - your Script-language seems Java- or C-like - so this matches very well IMO.
http://download.savannah.nongnu.org/rel ... 32-bin.zip
(small Hello-Dll-Examples are included - together with a short description, how to compile these Dll-examples, and how to automatically create Def-Files from already compiled Dlls with tiny_impdef).

And for those who want to write Std-Dlls in Basic-language, there is Freebasic available, the compiler also XCopy- installable - but this is the much greater package compared with tinycc - but the compiled Dlls are small too and probably somewhat easier createable (without Def-Files, but as I read from your reply you would need these Def-Files anyway for Opus) http://www.freebasic.net/ the compiler-environment http://www.radasm.com/fbedit/index.html and a good working IDE
- - - - - - - - - - - - -

Regards,

Olaf

[ Edit LL: Olaf can be found at http://www.thecommon.net/2.html -- as he wrote earlier, datenhaus DirectCOM.dll for dhSQLite is not suited to Opus since Opus does not use COM/ActiveX. However these discussions are helpful for sorting out ‘what can be done’. Thanks, Olaf.]


BTW, what we're discussing there is how to use SQLite DB and ship it embedded, and without need for client ODBC and without registering DLLs.

Larry

_________________
_good things come to those who wait(0)_


Top
 Profile  
 
 Post subject: The mystery of 'returning values' from DLLs using Opus CallF
PostPosted: May 21st, 2008, 8:21 am 
Offline
Godlike
Godlike

Joined: November 12th, 2005, 1:56 am
Posts: 1474
Location: SFBay Area
Opus: OpusPro v9.0x, & Evol.
OS: Vista32
System: Core 2 duo 2Ghz, RAM 3GB, Nvidia Go 7700 - laptop
I understand about 0.6% of recent DLL discussions. What I do realize is that the 'roadmap' to getting parameters in and values out is not clear.

So here is some Opusscript code from Olaf Schmidt that could be studied for insights on how he has it working... against the sqlite3.DLL.

This is the complete script that comprises the "SQLiteDllWrapper.ils" (May 11, 2008 from Olaf).

Code:
//Module containing sqlite3.dll-Wrapper-Functions, based on OpusScripts CallFn (developed by Olaf Schmidt)

//If you include this file under your Master-Page as external Script, then
//its functionality should be available in all your other Page-Scripts

var pOut = 0; //Module-Var, used to fake an Out-Param for the Opus-CallFn-Mechanism
var DBHdl = 0; //Module-Var, defining an opened DB, used in most wrapper-functions
var StmtHdl = 0; //Module-Var, defining an opened SQL-Statement, used in most wrapper-functions


//---------------------------- first some kernel32-Declarations ------------------------------------
var DllKernel = LoadDLL(SYSTEM_WINSYS_DIR + "kernel32.dll");

function GetOutPtr() {return DllKernel.CallFn("GlobalAlloc", false, "ulong", "ulong", 2, "ulong", 0);}
function DeRefOutPtr() {return DllKernel.CallFn("GlobalLock", false, "ulong", "ulong", pOut);} //small hack, to dereference the out-values for API-Params
function GetTickCount() {return DllKernel.CallFn("GetTickCount", false, "ulong");}
//--------------------------------------------------------------------------------------------------


//---------------------------- and now the sqlite3-Declarations ------------------------------------
var DllSQlite = LoadDLL(SYSTEM_PUBLICATION_DIR + "OpusSqlite\\sqlite3.dll"); //assuming a SubFolder OpusSQLite for your Project

function sqliteVersion() {return DllSQlite.CallFn("sqlite3_libversion", false, "string");}
function sqliteOpen(FileName) {return DllSQlite.CallFn("sqlite3_open", false, "ulong", "string", FileName, "ulong", pOut);}
function sqliteClose() {return DllSQlite.CallFn("sqlite3_close", false, "ulong", "ulong", DBHdl);}
function sqlitePrepare(SQL) {return DllSQlite.CallFn("sqlite3_prepare_v2", false, "ulong", "ulong", DBHdl, "string", SQL, "ulong", SQL.length, "ulong", pOut, "ulong", 0);}
function sqliteFinalize() {return DllSQlite.CallFn("sqlite3_finalize", false, "ulong", "ulong", StmtHdl);}
function sqliteColumnCount() {return DllSQlite.CallFn("sqlite3_column_count", false, "ulong", "ulong", StmtHdl);}
function sqliteColumnName(ZeroBasedIdx) {return DllSQlite.CallFn("sqlite3_column_name", false, "string", "ulong", StmtHdl, "ulong", ZeroBasedIdx);}
function sqliteStep() {return DllSQlite.CallFn("sqlite3_step", false, "ulong", "ulong", StmtHdl);}
function sqliteLastError() {return DllSQlite.CallFn("sqlite3_errmsg", false, "string", "ulong", DBHdl);}
//--------------------------------------------------------------------------------------------------



And then the script continues with code more specific to database operations via the SQLite engine (DLL).

Code:


//------ and finally a simple wrapper implementation, using the low-level-Declarations above -------

//try to open an existing DB, failing if the file cannot be found
function OpenDB(DBPath)
{
   if (pOut==0) pOut = GetOutPtr(); //ensure, we do this only once (in case pOut is Null yet)
   
   CloseDB(); //ensure we close an eventually unclosed DBHdl first, before we open a new one
   
   if (FileExists(DBPath) == 0) //file does not exist
   {   
      Debug.trace("DB-File not found at: " + DBPath + "\n");
      return 1;//signalize an error with a return-value !=0
   }
   var result = sqliteOpen(DBPath);
   if (result == 0) DBHdl = DeRefOutPtr(); //Zero means no error - so we set the DBHdl-variable
   return result;
}

//a pendant to OpenDB above, but able to create a new DB, if the File doesn't exist
function CreateOrOpenDB(DBPath)
{
   if (pOut==0) pOut = GetOutPtr(); //ensure, we do this only once (in case pOut is Null yet)
   
   CloseDB(); //ensure we close an eventually unclosed DBHdl first, before we open a new one

   var result = sqliteOpen(DBPath); 
   if (result == 0) DBHdl = DeRefOutPtr(); //Zero means no error - so we set the DBHdl-variable
   return result; //a result-value of Zero means SQLite_OK, if not Zero, then a failure occured
}


//you need to enclose your DB-Interaction within one of the Open-Calls above and this one, which cleans up
function CloseDB()
{
   if (DBHdl != 0) sqliteClose();
   DBHdl = 0; //reset the DBHdl-variable to 0 after this call, to signalize the closed State
}

//delivers a RowSet, based on an SQL-String
function GetRowArray(SQL)
{
   
   PrepareStatement(SQL); //Ok, lets see, if the SQL-Statement is valid
   
   var Rows = new Array();
   if (StmtHdl==0) return Rows; //return with an unfilled Rows-Array, since the Statement was not valid
   
   var ColumnCount = sqliteColumnCount();
   
   //first we get the Column-Names
   var Columns = new Array();
   for (var j = 0; j < ColumnCount; j++) Columns[j] = sqliteColumnName(j);
    Rows[0] = Columns; //fill the Column-Name-Array into Row[0]
   
   //now the loop over the real record-content using sqliteStep
   var i = 0;
    while (sqliteStep() == 100) // 100 means: step was able to position at a (next) record
   {
      Columns = new Array(); //each Row gets a new SubArray for the Columns
      
      //and here's the Sub-Loop over the current Records-Columns, retrieving the content as Text
      for (var j = 0; j < ColumnCount; j++)
      {
         //here we call directly (instead using a nicer Definition as e.g. done for sqliteColumnName
         //inside the Declares-Section for the sqlite3.dll above), because this is the most time-consuming part
         Columns[j] = DllSQlite.CallFn("sqlite3_column_text", false, "string", "ulong", StmtHdl, "ulong", j)
      }
      i++; Rows[i] = Columns;
   }
   
   sqliteFinalize(); StmtHdl = 0; //reset our Statement-Handle
   return Rows;
}

function ExecuteStatement(SQL)
{
   PrepareStatement(SQL); //Ok, lets see, if the SQL-Statement is valid
   if (StmtHdl==0) return false; //no success with the Statement, so we return false
   
   var result = sqliteStep();
   if ((result < 100) && (result > 101)) //an error in sqliteStep
   {
      sqliteFinalize(); StmtHdl = 0; //reset our Statement-Handle
      return false;
   }
   
   sqliteFinalize(); StmtHdl = 0; //reset our Statement-Handle
   return true;
}

//small helper, used to prepare and check an SQL-statement for validity
function PrepareStatement(SQL)

   if (StmtHdl != 0) sqliteFinalize(); //make sure the StmtHdl is closed, before we try to get a new one
   StmtHdl = 0;
   
   if (sqlitePrepare(SQL) != 0)
   {
      Debug.trace(sqliteLastError() + "\n"); //put out the error with the SQL-statement
      return 0;
   }
   StmtHdl = DeRefOutPtr(); //success with preparing the SQL-Statement, so we set the appropriate Handle
}





Pretty crisp code, huh?

FYI, this evolved out of a lengthly discussion of how to use SQLite DB engine with Opus. Just search 'SQLite' in this forum and you'll find database details and a working Demo. (April-May '08 ). In short, SQL Statements can be written in the usual working scripts and passed into the above code ("wrapper")... with the main entry function being: function GetRowArray(SQL)

Post back if you discover any useful ways to apply these constructs.

Cheers,
Larry


ps. this may also be useful:
http://www.paris-pc-gis.com/mb_r/dll/dl ... _start.htm
That site outlines DLL arguments and return values for certain Windows libraries... kernel, etc. May be somewhat 'old', but still valid?

_________________
_good things come to those who wait(0)_


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ]  Go to page Previous  1, 2

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 46 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group