Author Topic: Couple Api ideas for embedding  (Read 63847 times)

dzzie

  • Moderator
  • *****
  • Posts: 44
Re: Couple Api ideas for embedding
« Reply #15 on: June 06, 2014, 10:40:51 AM »

thanks John, once it gets a bit more along I will post some external extension dlls and scripts to play with :)

on the initialization/cleanup thing, just realized no need to get fancy, they can just be called manually easily enough since the embedded host is the one calling run

dzzie

  • Moderator
  • *****
  • Posts: 44
Re: Couple Api ideas for embedding
« Reply #16 on: June 14, 2014, 03:08:42 PM »
attached is the COM extension compiled as a dll along with a vb6 com object for testing and 2 test scripts.
you can set com_dbg =1 and recompile the extension to see debug output.

support

  • Administrator
  • *****
  • Posts: 859
    • Script BASIC Open Source Project
Re: Couple Api ideas for embedding
« Reply #17 on: June 14, 2014, 04:42:45 PM »
Quote from: Dave's README

This is a script basic extension to add support for creating COM objects
and calling their methods.

The COM objects must support the IDispatch interface so they can be used from
scripting clients. (This is very common)

Visual Studio 2008 project files have been included. They are set to use
the script basic include directory as relative path ./../include/

The COM.dll will be compiled into the current directory.

Notes:

Script basic only supports several data types internally, COM supports
many.

In testing with VB6 COM objects, the VB6 methods were forgiving
with data types. If the VB6 method expected a byte type, it would accept
a long (VT_I4) so long as the value was < 255.

The two main types this extension handles are longs and strings which it will
proxy between script basic and COM types automatically.

The CallByName function accepts an arbitrary number of arguments. These are
translated and copied into a DISPPARAMS array to be passed to the COM object.

The prototype of this function is:

callbyname object, "procname", [vbcalltype = VbMethod], [arg0], [arg1] ...

Where object is a long type returned from CreateObject() export.

If you are working with embedding ScriptBasic in your own application,
you can also use CallByName to operate on host created COM objects such as
VB6 Form, Class and GUI objects.

All you need is for the host application to provide an ObjPtr() to the
script to give it full access.

More details on this are available here:
  http://sandsprite.com/blogs/index.php?uid=11&pid=310

The VB6_Example.dll is a sample COM object that COM_VB6_Example.sb script uses
to show the results of some tests with common data types, retrieving strings and
longs, displaying a UI, and manipulating VB6 Form COM objects

In order to use this ActiveX Dll on your system you will have to run regsvr32 on it
or compile it yourself. The easiest way to register it is

start -> run -> type regsvr32 -> drag and drop the dll file into the run textbox to
have its path added as the argument.

remember com.dll has to be in the script basic modules directory and
com.inc should be in the includes directory to use these samples.
Script BASIC Project Manager

dzzie

  • Moderator
  • *****
  • Posts: 44
Re: Couple Api ideas for embedding
« Reply #18 on: June 14, 2014, 04:55:41 PM »
another note worth sharing, if you dont have VB6, you can use the free VB5 Control Creation Edition (CCE) to create whatever activex controls you want for GUIs etc. I dont think MS still has a link up but still available on the net. It was literally free but could only make ActiveX controls. released when they were tryign to gain market share with IE and pushing COM

support

  • Administrator
  • *****
  • Posts: 859
    • Script BASIC Open Source Project
Re: Couple Api ideas for embedding
« Reply #19 on: June 14, 2014, 05:02:02 PM »
Thanks Dave for the upload and sitting on the edge of my chair getting this installed.  ;D

I have VB6 installed on my XP VirtualBiox which I'm going to try first before giving Win7 64 a try.

Does your extension module add XP theme support? 
Script BASIC Project Manager

dzzie

  • Moderator
  • *****
  • Posts: 44
Re: Couple Api ideas for embedding
« Reply #20 on: June 14, 2014, 05:44:12 PM »
I didnt do anything with themeing, I still use classic lol. I think any theme related code would just be in the VB6 GUI portion and is independent of the COM part. I havent tried to compile or test the com.dll as x64 yet but should be ok i think. I am not sure if MS has a x64 version of SAPI.spVoice available but they probably do.

support

  • Administrator
  • *****
  • Posts: 859
    • Script BASIC Open Source Project
Re: Couple Api ideas for embedding
« Reply #21 on: June 14, 2014, 05:53:25 PM »
Here is some screen shots of the COM_VB6_Example.sb program running on XP using VB6 resources.

          







Quote
C:\SB22\sbcom>scriba COM_VB6_Example.sb
GetString returned: Script BASIC
objForm = 1414336
Waiting until user closes form to proceede..
anndddd were done!

C:\SB22\sbcom>

Code: [Select]
import com.inc

obj = CreateObject("VB6.Sample")

'Sample function prototypes
' longTest(v As Long)
' intTest(v As Integer)
' ByteTest(v As Byte)
' GetString(prompt As String, title, def) As String
' ShowUI() As Long

if obj = 0 then
print "CreateObject failed!\n"
else
    CallByName(obj, "longTest", VbMethod, 20000)
    CallByName(obj, "intTest", VbMethod, 1000)
    CallByName(obj, "byteTest", VbMethod, 255)
   
    'this one fails silently because its invalid value for byte type..
    CallByName(obj, "byteTest", VbMethod, 256)

    retVal = CallByName(obj, "GetString", VbMethod, "Enter some Text:", "my title", "default value!")
    print "GetString returned: ", retVal, "\n"
   
    'do NOT release objects you dont own..
    objForm = CallByName(obj, "LaunchUI")
    print "objForm = ", objForm, "\n"
   
    for i=0 to 10
        CallByName(objForm, "AddItem", VbMethod, "Hello from script basic! " & i)
    next
   
    print "Waiting until user closes form to proceede..\n"
    CallByName(obj, "BlockUntilFormCloses")
   
    ReleaseObject(obj)
    print "anndddd were done!\n"
   
end if

FYI The SAPI COM example works fine.

VB6 & XP Themes  - I couldn't get the manifest method to work with your example.
« Last Edit: June 15, 2014, 12:07:31 AM by support »
Script BASIC Project Manager

support

  • Administrator
  • *****
  • Posts: 859
    • Script BASIC Open Source Project
Re: Couple Api ideas for embedding
« Reply #22 on: June 15, 2014, 08:07:35 PM »
Dave,

I created a form with a calender control and wanted to see if I could make it work with Script BASIC. Can you post the steps needed to use VB forms with SB?


« Last Edit: June 15, 2014, 08:09:48 PM by support »
Script BASIC Project Manager

Verhas

  • ScriptBasic Developer
  • *****
  • Posts: 17
Re: Couple Api ideas for embedding
« Reply #23 on: June 16, 2014, 04:25:25 AM »
One thing I am not sure on is if I want to give script clients live object handles for them to passback
and me use blindly. Its kind of a bad idea. try catch and is null checks can handle some ok, but a random number
passed in could easily lead to memory corruption even if try catch kept execution going for now. Safer would be to
only pass back quasi handles I suppose and then validate them from an internal hash map to real value.

You can maintain an array of pointers to objects to pass to the script and pass only the index and use the same array in the extension module. Extension modules access the extension pointer so this is possible to pass one object from the embedding application to the extension module function without any interaction in the BASIC script. Thus the array need not be "global".

Any other solution is more error prone. You could pass the actual pointer and check that the pointer is present in the pointer set, but then the pointer can also be passed to another module, or can be "poked" and memory may corrupt.

I am thrilled how deep you digged into ScriptBasic. There are only a very few men who did that in the past. If you get stuck feel free to write me mail, skype whatever.

dzzie

  • Moderator
  • *****
  • Posts: 44
Re: Couple Api ideas for embedding
« Reply #24 on: June 16, 2014, 07:06:33 AM »
I have updated the example dll with a SelectDate function which shows a GUI with the calendar control. It returns a string based date. I have included comments in the source detailing how it works as well.

I was not able to get themes to work either on quick test. I am thinking maybe the manifest must be for the scriba.exe.manifest and then have the script call InitCommonControls api before plugin launch? Not sure exactly how but it should work somehow (although maybe not from a console process?) There are also skinning solutions but they are a mountain of code.

Thanks for the offer Peter I will take you up on that when i get stumped :) C is not my strongest language, but I am finding the source quite agreeable and able to find and follow along through most things!
 
One weakness of the object handle lookup, like in these COM examples, the CallByName function is returning COM object handles themselves which would not be unusable directly without the extra step of calling an int RegisterObject(hObject) from the script after one was received. I suppose not really a weakness, just an extra step required then in name of safety

One other thing that would be nice to add is a way for the GUI to initiate call backs into script basic functions from UI events. Might look into that as well. The exports are available in scriba.exe although they are cdecl. It can be done but requires use of some tricks using asm thunks . natively vb6 only supports stdcall. Doing this from a embedded host would be easier I am sure.

« Last Edit: June 16, 2014, 07:11:11 AM by dzzie »

dzzie

  • Moderator
  • *****
  • Posts: 44
Re: Couple Api ideas for embedding
« Reply #25 on: June 16, 2014, 07:53:07 AM »
For reference the steps are:

1) Create  new ActiveX Dll project in VB6

2) Set project -> project properties -> project name textbox to be name you want. In example we used VB6 this will be used in program id to CreateObject

3) Add a new class and rename it to what you want. In example we used Sample. Make sure its instancing is multiuse (default). The program ID to create an instance of this class would now be CreateObject("VB6.Sample")  (format is libraryname.classname although can also be {clsid})

4) add a public function/sub/property to the class. A public variable will probably also work.

5) to show a form add a form to the project, now decide if you want it to be displayed modally or non-modally. examples for both are show in example.

Non-modal form allows you to manipulate the forms Public members from script basic, then you can use a BlockUtilFormCloses type method to pause script basic execution until the form is closed.

A modal form will block execution until the form is closed on its own, but you will have to do any initilizations of it from the initial function call arguments (such as prompts, titles, default values etc)

6) once the GUI is done it will return a value back to script basic. Callbacks from UI elements such as button clicks to script basic functions is not yet supported.

support

  • Administrator
  • *****
  • Posts: 859
    • Script BASIC Open Source Project
Re: Couple Api ideas for embedding
« Reply #26 on: June 16, 2014, 08:09:24 AM »
Thanks Dave for the update and Peter for helping out.

Take a look at the trial extension module and the myicall function. This shows you how to call SB script functions from the extension module. (my utopia I'm striving for in the IUP ext. module) Charles has already done this in DLLC and in fact doing it multi-threaded with a common shared event handler. IUP isn't thread safe by design but that didn't stop Charles.

I will test the calendar control and let you know how it goes. This is too cool being able to call VB forms and interact with them.

I created a Windows version of scriba called scriabw.exe and sbiup.exe which are consoleless Windows versions with themeing support enabled. Works great with IUP. When I tried them with your stuff, nothing is displayed and doesn't return to the console prompt like it should.  ??? I wonder if you disable alert dialogs the main form may theme. (noticed this problem early on with DYC)



« Last Edit: June 16, 2014, 08:17:03 AM by support »
Script BASIC Project Manager

support

  • Administrator
  • *****
  • Posts: 859
    • Script BASIC Open Source Project
Re: Couple Api ideas for embedding
« Reply #27 on: June 16, 2014, 10:49:06 AM »
The MS calender ActiveX example works great!



This is the added code to the above example to show the calender dialog.
Code: [Select]
    sDate = CallByName(obj, "SelectDate")
    if len(sDate) = 0 then
    print "User pressed cancel for date selection\n"
    else
    print "Date: ", sDate, "\n"
    end if

Console output
Quote
C:\SB22\sbcom\sbvb2>scriba COM_VB6_Example.sb
GetString returned: default value!
objForm = 1414640
Waiting until user closes form to proceede..
Date: 16/6/2014
anndddd were done!

C:\SB22\sbcom\sbvb2>
Script BASIC Project Manager

dzzie

  • Moderator
  • *****
  • Posts: 44
Re: Couple Api ideas for embedding
« Reply #28 on: June 16, 2014, 05:52:27 PM »
ok got the callbacks working. but I had to cache a pSupportTable pointer when entering CallByName, the VB is single threaded and modal blocking..sooo should be safe I think. The following is about as clean as i can see it getting..

Code: [Select]
import com.inc

function Button1_Click(arg)
print "Back in script basic Button1_Click arg=", arg, "\n"
Button1_Click = arg + 1
end function

function Button2_Click(arg)
print "Back in script basic Button2_Click arg=", arg, "\n"
Button2_Click = arg * 2
end function

obj = CreateObject("VB6.Sample")

if obj = 0 then
    print "CreateObject failed!\n"
else
    print "obj = ", obj, "\n"
       
    oCollection = CallByName(obj, "CallBackHandlers", VbGet)
    print "oCollection = ", oCollection, "\n"
   
    CallByName(oCollection, "Add", VbMethod, ADDRESS(Button1_Click()), "frmCallBack.cmdOp1_Click" )
    CallByName(oCollection, "Add", VbMethod, ADDRESS(Button2_Click()), "frmCallBack.cmdOp2_Click" )
   
    retVal = CallByName(obj, "LaunchCallBackForm", vbMethod, 21)
    print "LaunchCallBackForm returned ", retVal, "\n"
   
    ReleaseObject(obj)
    print "test complete!\n"
end if

you will have to change the project -> properties -> C++ -> additional include directories to compile the com.dll on your system.

so the way it works is the script registers which function handler it wants to use for each button event. The event names are actually
arbitrary, its just a format that both the script and the activex control agree on. Then when the button is clicked on in the UI, it will query
the registered handlers for the nodeID for the collection key it uses. Then does the call back passing an int arg.

consider it an experimental design at this point I guess. maybe a different design would be more useful or cleaner but its what I came up with as a first take.

support

  • Administrator
  • *****
  • Posts: 859
    • Script BASIC Open Source Project
Re: Couple Api ideas for embedding
« Reply #29 on: June 16, 2014, 06:02:59 PM »
Quote
you will have to change the project -> properties -> C++ -> additional include directories to compile the com.dll on your system.

Are you saying I need to do this to test this callback example or if I'm doing something new?

I only use the console VC compiler and Visual Studio isn't something I'm proficient with. 

Why does it have to be compiled on my XP box? I can match what directory structure you use. Having Script BASIC programmers compiling C++ DLLs to make this work may be over their heads.

Update

I'm guessing it's working (or not). It popped dialogs saying the callbacks weren't registered or something like that..

C:\SB22\sbcom\sbvb3>scriba COM_VB6_CallBack_Example.sb
obj = 1414352
currently unsupported VT return type: 9
oCollection = 0
LaunchCallBackForm returned 21
test complete!

C:\SB22\sbcom\sbvb3>
« Last Edit: June 16, 2014, 06:13:56 PM by support »
Script BASIC Project Manager