ScriptBasic

Extension Modules => Extension Modules => COM => Topic started by: dzzie on May 29, 2014, 06:30:01 PM

Title: Couple Api ideas for embedding
Post by: dzzie on May 29, 2014, 06:30:01 PM
Hi all,

Just found the project and I am really impressed with it. Before I start I will mention my goal. I would like to create a basic script control similar to MS Script control but with debugging / single step/ variable inspection support. So I am coming from the task of an embedded user.

ScriptBasic looks like it is a good fit for this and I have been experimenting with it for about a week now. So far I have added the following (simple) API

Code: [Select]
//text config to binary
scriba_CompileConfig

//add a preprocessor dll explicitly by dll path, no config needed
scriba_LoadInternalPreprocessorByPath

//register a compiled in preprocessor with no need for external dll
scriba_LoadInternalPreprocessorByFunction

I have also had success compiling extensions directly into the interpreter and accessing them via the declare mechanism (even when working from an exe test project) This seemed easier to me than writing a new command so far.

I see that the interpreter has support to call script functions and getting/setting global variables. I was looking for an easy way to have a host app register a new function to be available to scripts maybe something like

Code: [Select]
scriba_registerNative(pProgram, "myFunc", &myFunc_handler)

Thats when I took a side street and figured out to use a compiled in extension for this task.

Code: [Select]
declare sub trial alias "trial" lib "test.exe"

Bit of a hack but it works so I can move on to experiment with next task of wiring access to the now compiled in debugger preprocessor to a VB6 GUI. Once this is fleshed out, I can add in a scintilla based syntax highlight control I have and add proper debug controls around that.

Ultimate goal for me is to make an embeddable script control ocx with a script editor IDE + debug support and some kind of support for VB6 COM objects.

For COM support, I was thinking of something like:

Code: [Select]
scriba_registerNameSpaceResolver(pProgram, "myObj", &my_resolver)

so if the script engine sees myObj::myfunc(1,2)

it will call my_resolver() with the args "myfunc", 1, 2 or something like that, but after looking through the syntax and lexer code I think it would be tricky to slip this in. An easier solution is probably to use the extension trick to

Code: [Select]
declare sub callObj alias "callObj" lib "test.exe"
a = callObj("myObj.myFunc", 1 , 2)

Then the VB6 CallByName function will be put to good use, but you will be limited to accessing the primary functions/properties of the object I think. (ie myObj.itsObj.someProp probably wont work at least not  without some parsing and intermediate steps). Not the prettiest, but manageable.

John also mentioned Charles Pegge's (OxygenBasic author) DLLC COM extension which I will study as well.

Again really impressed with the project, I have wanted this type of script control for a loooong time. I can see all the pieces fitting together here.

My work in progress can be found here:  https://github.com/dzzie/ScriptBasic_Control

As always, any/all ideas or comments welcome :)

-Dave



Title: Re: Couple Api ideas for embedding
Post by: Support on May 30, 2014, 08:21:13 AM
Welcome Dave!

Interesting stuff. Can you post your Visual Studio project file when you get everything working? It would be nice to have an alternative way to compile Script BASIC for Windows other than Peter's setup.pl method. I current have VS 2013 install on Win 7 64.


Title: Re: Couple Api ideas for embedding
Post by: dzzie on May 30, 2014, 12:26:35 PM
the solution and project files are included in the git repository (also a .zip download link) https://github.com/dzzie/ScriptBasic_Control/archive/master.zip (https://github.com/dzzie/ScriptBasic_Control/archive/master.zip)

My physical file layout is slightly different and does not include all files in the distro, but you can see the project settings used.
You could also remove the files I have set in there and re-add (just drag and drop a multiselection of files or a folder into the VS treeview and it will add all files in that dir to the project)

There are ways to add multiple projects to one solution file so you can "Build All" and it will compile each exe, dll , preprocessor, extension etc all at once.
Setting all that up might take a while though it can be allot of fussing. I think basically you make copies of a vcproj file you are using, set up each one individually to build the target you want, then from the top level solution file, you can "Add project". so each binary gets its own project file, all linked into
the top level solution file. Its kind of a pita.

Sometimes I just use a VS project just for code navigation and editing, then use the custom build scripts authors provide for the actual compilation. Actually there is probably a way to set a custom build step to use the perl script and not the standard VS compilation process. So you probably can just add all the files to one
solution file for editing/viewing/navigation, then hit build and it will call the perl script. Not sure if it will display compilation errors as nicely as normally though.
 
Title: Re: Couple Api ideas for embedding
Post by: Support on May 30, 2014, 12:37:48 PM
For a release build, Peter's method would be preferred as everything (.h, syntax tables, error codes, documentation, ...) is built from scratch from the C files.

Armando (AIR) created a custom SB master make file for gcc under Windows that works pretty well.

Title: COM progress
Post by: dzzie on June 03, 2014, 07:45:15 AM
thought I would share another bit of progress. I think a generic COM extension is about 90% done now and working in tests.
(currently i have it compiling into the main exe for debugging, no dll available yet but should be able to be built as one)

https://github.com/dzzie/ScriptBasic_Control/blob/master/engine/extensions/COM.cpp

Code: [Select]
declare sub CreateObject alias "CreateObject" lib "test.exe"
declare sub CallByName alias "CallByName" lib "test.exe"

const VbGet = 2
const VbLet = 4
const VbMethod = 1
const VbSet = 8

obj = CreateObject("SAPI.SpVoice")

if obj = 0 then
print "CreateObject failed!\n"
else
CallByName(obj, "rate", VbLet, 2)
CallByName(obj, "volume", VbLet, 60)
CallByName(obj, "speak", VbMethod, "This is my test")
end if

print "\n\nPress ENTER..."
line input a

'in vbscript this would be:
'----------------------------------------
'Set voice = CreateObject("SAPI.SpVoice")
'voice.Rate = 8
'voice.Volume = 60
'voice.Speak "Hello, world!"
Title: Re: COM progress
Post by: Support on June 03, 2014, 08:03:58 AM
Dave,

Great progress! I'm looking forward to start using some of this code.

Do you think this would work with Mono as well? (COM & Mono (http://www.mono-project.com/COM_Interop))

Quote
Note that there is very little that ties COM Interop to Windows. COM is a binary standard, so anyone who follows that standard can use the COM Interop functionality in mono.

John
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 03, 2014, 04:07:09 PM

Not sure I understand so I will kinda talk out loud.

Its true the COM standard can be implemented as a method of Interface and function pointer discovery on any system. Its just a communication protocol.

If the question is could this technique be used to call .NET code written in Mono, its possible I suppose. I know C# has a way of registering .NET classes for use with COM by using a COM visible attribute, creating a typelib, and registering itself in the registry. Going from COM to .NET and back feels like functionality that MS shoehorned in for compatibility reasons.

I have also seen an example where shellcode could initialize the .NET runtime and call code written in IL for execution. If i wanted to interact with .NET code I think I would look first at this technique because it probably does not require special registration of the .NET classes on the target system.

(this isnt the example i was thinking of but all i could find in a quick search)
http://blog.didierstevens.com/2010/04/13/net-shellcode/

I havent looked at these examples in depth but I would say being able to host the CLR in your code and let script basic call out to its methods should be doable from the shellcode example.

It comes down to having clients to talk to and how to you find them. On Windows COM is heavily registry dependent to locate the class containers (dlls)


Title: Re: COM progress
Post by: Support on June 03, 2014, 04:23:47 PM
Dave,

Is this a 32 bit Windows only solution? IUP has a OCX container (ATL) that the webview control runs in. Maybe it could be used with your extension module.

Thanks for all the hard work you have put into this.

John
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 03, 2014, 04:56:39 PM

I have been a high level COM user mostly, and have dealt with the low level details just a handful of times.

I believe you can write 64bit COM servers. COM also supports remote servers such as a machine across the network
and out of process servers like a seperate exe on same machine. Right now I have only specified it to create in process servers which means that only 32bit servers could be used if it was compiled in 32bit mode.

I have not tested if it compiles properly for x64. I will be using it for interacting with VB6 COM classes (dlls) which are exclusively
32 bit. My dev system is only 32 bit as well. I have been avoiding the WOW64 environment because of things like file and registry redirection. Since VB6 is limited to 32 bit only it just adds headache and no value.

As far as interacting with OCX controls. In order host a container you need to implemented a bunch of COM interfaces to give
it a place to display itself. I have no experience with these on a low level in C. Just calling methods on a COM object probably arent enough to display a GUI unless it has methods like CreateForm etc. OCX can also house regular COM classes as well so this is possible for self hosting I have a hexeditor control like this.

The experiments I am currently do with this are my cutting edge of what I can pull off lol. Which is what makes it fun :)
Cross platform dev, 32/64 compatiable code and low level COM are all new to me so no guarantees on what changes may be needed to get it to work outside of the environment I am building this for.
Title: Re: Couple Api ideas for embedding
Post by: Support on June 03, 2014, 05:08:25 PM
The IUP ATL container takes care of all the display and initialization issues. It doesn't provide method and and event support. There is Lua COM support for the container but that is about it.
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 03, 2014, 05:21:32 PM
If it has something like RegisterCallBack for you to set event handlers from passed in function pointers then it would be hopeful.
Title: Re: Couple Api ideas for embedding
Post by: Support on June 03, 2014, 05:25:20 PM
Take a look and the IUP (PUI) SB extension module. All events go through a common message handler function. IupLoopStepWait() In DLLC the SB script functions are called directly. With my C extension module for IUP it returns back to SB on an event and i do an ICALL with the address of the script function. I have a set of C callback functions that IUP calls and sets global variables I reset after access in another call if needed.


Title: Re: Couple Api ideas for embedding
Post by: Verhas on June 05, 2014, 04:19:34 AM
Wow this is impressive what you do with this interpreter. I am amazed.

As for the API suggestions my 2cents:

namespace lookup hooking is an interesting approach. The issue is that ScriptBasic was not designed to support namespaces. This is only a naming trick. The namespace:: prefix becomes part of the name and that is it.

Code: [Select]
scriba_registerNative(pProgram, "myFunc", &myFunc_handler)

is also an interesting idea, but it can actually be solved defining an external module. Note that the external module can be "part" of the embedding application. It does not need to be a DLL (or .so in UNIX). It can be statically linked to the application and be available to the interpreter so it can call the method. Note that the function pointers are defined in a table for the modules (as far as I remember, I have not touched it for 8 years now). In that table there is a

Code: [Select]
"myFunc" , &myFunc_handler

part that defines the function entry point and the associated name. It is true that you can not have different associations for different pProgram objects. It is static.

Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 05, 2014, 06:55:35 PM
Hi Peter

thanks for the ideas and the great code base !

 The internal extension is working well. Currently if more than one internal extension is compiled in besSUB_START and friends would conflict is only problem I see. I think this will be easy to work around by prepending module name to it.

Code: [Select]
#define besSUB_START  besFUNCTION(bootmodu)
#define MODULE_INITIALIZER "bootmodu"
/* modumana.c call the module initializer function */
FunctionPointer = modu_GetModuleFunctionByName(*ThisModule,MODULE_INITIALIZER);

so if functionPointer == NULL then maybe secondary check something like

Code: [Select]
sprintf(buf, "%s_bootmodu", (*ThisModule)->pszModuleName)
FunctionPointer = modu_GetModuleFunctionByName(*ThisModule,buf);

seems like should work. actually in further thought..maybe it wont I was thinking of preprocessor name, pszModuleName is probably taken from declare i havent step breakpoint yet to check for sure.  (also forgot to mention above I also had to disable strcat for dll extension to module name for it to work from exe.) Some variation of this concept will work anyway though.

I also found a good article on x64 COM.

http://mariusbancila.ro/blog/2010/11/04/32-bit-and-64-bit-com-servers/

Have not had a chance to look at the IUP yet except glance. Looking into IConnectionPoint maybe interesting experiment to see about how to connect call back events from COM back to SB event handlers something like

Code: [Select]
'sb code
ConnectEvents(objPtr, "objName")

sub objName_Clicked

then in C I imagine it works something like take objPtr, enumerate events object supports
then check script to see if objName_[event name] exists..if it does then handle the event and
call the sub manually when its hit. Interesting to think of the logistics of it anyway. Sinking events
may be required for IUP OCX as well from sounds of it.

More time to play on the weekend.

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.

embedded clients who do things like AddObject to make object available to script would have to add to list as well.
Only down side is if a COM object returned another COM object, the script would not be able to use it now since
the manager would not be aware of the pointer being valid. (or script could be given access to register its own then
stability is all in their hands)

anyway i think the COM extension will be left for a while now. majority is done, will need to build out the other components
to circle back and start really using it to see what more it needs. One surprising thing, if a vb com object expects a byte type (VT_I1), it will accept a VT_I4 and .lvalue as long as value < 255. I suppose not so surprising since I think the value is a union, but still seems like it is being kind with an auto conversion accepting different type in background. I will have to test some ATL based clients to see if they are as kind.

but so far so good :)



Title: Re: Couple Api ideas for embedding
Post by: Support on June 05, 2014, 07:43:31 PM
Great progress Dave!

Let me know if you need some help with testing.

Quote
Currently if more than one internal extension is compiled in besSUB_START and friends would conflict is only problem I see.

Each internal extension should be compiled into its own object library. I assume SB skips the whole DLL handshacking routine knowing that it's static linked. (no load/unload stuff going on or version checking needed) Peter would have to validate my understanding if it's true or not.

Title: Re: Couple Api ideas for embedding
Post by: dzzie 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
Title: Re: Couple Api ideas for embedding
Post by: dzzie 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.
Title: Re: Couple Api ideas for embedding
Post by: Support 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.
Title: Re: Couple Api ideas for embedding
Post by: dzzie 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
Title: Re: Couple Api ideas for embedding
Post by: Support 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? 
Title: Re: Couple Api ideas for embedding
Post by: dzzie 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.
Title: Re: Couple Api ideas for embedding
Post by: Support 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.

(http://files.allbasic.info/ScriptBasic/SBCOM/d1.png)     (http://files.allbasic.info/ScriptBasic/SBCOM/d2.png)     (http://files.allbasic.info/ScriptBasic/SBCOM/d3.png)

(http://files.allbasic.info/ScriptBasic/SBCOM/d4.png)

(http://files.allbasic.info/ScriptBasic/SBCOM/d5.png)

(http://files.allbasic.info/ScriptBasic/SBCOM/d6.png)

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 (http://support.microsoft.com/kb/309366)  - I couldn't get the manifest method to work with your example.
Title: Re: Couple Api ideas for embedding
Post by: Support 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?

(http://files.allbasic.info/ScriptBasic/SBCOM/sbcal.png)
Title: Re: Couple Api ideas for embedding
Post by: Verhas 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.
Title: Re: Couple Api ideas for embedding
Post by: dzzie 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.

Title: Re: Couple Api ideas for embedding
Post by: dzzie 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.
Title: Re: Couple Api ideas for embedding
Post by: Support 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)



Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 10:49:06 AM
The MS calender ActiveX example works great!

(http://files.allbasic.info/ScriptBasic/SBCOM/sbvbcal.png)

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>
Title: Re: Couple Api ideas for embedding
Post by: dzzie 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.
Title: Re: Couple Api ideas for embedding
Post by: Support 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>
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 16, 2014, 06:15:00 PM

oghh no sorry, wasnt clear.

The precompiled com.dll will work fine.

I just meant If you want to play around and recompile the com.dll for some reason using the provided solution file.
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 16, 2014, 06:17:03 PM
if it said callbacks werent registered its probably because you forgot to register the vb6_example.dll again with regsvr32
since the interface has changed the clsids in teh registry have changed as well so it must be reregistered

Code: [Select]
C:\scriptbasic\bin>scriba COM_VB6_CallBack_Example.sb
obj = 1416200
oCollection = 1418968
Back in script basic Button1_Click arg=21
Back in script basic Button1_Click arg=22
Back in script basic Button1_Click arg=23
Back in script basic Button1_Click arg=24
Back in script basic Button2_Click arg=25
Back in script basic Button2_Click arg=50
Back in script basic Button2_Click arg=100
Back in script basic Button2_Click arg=200
LaunchCallBackForm returned 400
test complete!

Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 06:19:16 PM
I thought that is what you meant. Didn't want to scare anyone away before it's out of the kitchen.  :)

Can you confirm the output I posted was what you expected?

With each release I put it in a sub-directory of sbcom. I then regsrv the DLL again due to it's new location.

Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 16, 2014, 06:20:48 PM
also the currently unsupported VT return type: 9 message shows it was an old version of com.dll that was loaded

actually sorry i will still need a little more work on this..when I switched over to release build a setting didnt carry over
and the last couple tweaks I was still testing the old debug build :(

thats what I get for being fancy and using a post build command to install the extension for me
Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 06:25:06 PM
I re registered it again but it still says the script writer forgot to register the callback handler.

I'm on the #AllBASIC IRC (see link for web client in  upper right corner of forum) if that would be better to resolve this.
Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 06:34:12 PM
I forgot to copy the com.dll to the SB modules directory. I also copied the com.inc to the include directory. Now it GPF's.  :'(
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 16, 2014, 06:37:17 PM
ok sorry about that, I am at the end of a 15hr day :(

it was a last minute change i had made and thought it tested fine this should be it.

Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 06:44:00 PM
1. Over wrote directory with new zip.
2. Copied com.dll to modules dir.
3. Copied com.inc to include dir.
4. Re-registered VB6_Example.dll.

GPF after I press one of the callback test buttons.

C:\SB22\sbcom\sbvb3>scriba COM_VB6_CallBack_Example.sb
obj = 1414352
oCollection = 1414432

C:\SB22\sbcom\sbvb3>
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 16, 2014, 06:45:28 PM
in other news, I will make a quick screen cast video tomorrow on debugging with the visual studio IDE.
It has amazing debugging tools, I am so spoiled by them now.

Last project I worked on was a gcc/cygwin build. I spent like 2 weeks of vacation solid
converting it over to compile under VS fighting through all kinds of obscure errors just so I could get
to use the VS debugging tools for future dev on it. 
Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 06:47:15 PM
I have Visual Studio 2013 on Win7 64 and VS2008 on XP.

I really like using MinGW-GCC-TDM.
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 16, 2014, 06:48:55 PM
you might have to compile COM.dll for your system then if your version of scriba.exe is built from newer sources
than mine. If anything changed in the pSupportTable offsets, or pProgram offsets or pExecutionObject table offsets
it would be a guaranteed crash

The scriba I compiled against is

File:     scriba.exe
Size:     507904
MD5:      3DCCF6B74C1846CB7EC08E7F657279DB
Compiled: Sat, Sep 12 2009, 3:19:33  - 32 Bit EXE

must sleep now will resume the fight in teh am

ok mailed, the exe I am using is from the public download
Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 06:50:13 PM
Please e-mail me the scriba.exe you are using.

What I'm using.

C:\SB22\sbcom\sbvb3>scriba -v
ScriptBasic v2.2
Variation >>Windows32<< build 2
Magic value 859012665
Node size is 16
Extension interface version is 11
Compilation: Nov  9 2012 18:29:05
Executable: C:\SB22\bin\scriba.exe

C:\SB22\sbcom\sbvb3>

Here is a later compiled version but still GPF's.

C:\SB22\sbcom\sbvb3>scriba -v
ScriptBasic v2.2
Variation >>Windows32<< build 2
Magic value 859001395
Node size is 16
Extension interface version is 11
Compilation: May  3 2014 21:45:37
Executable: C:\SB22\bin\scriba.exe
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 16, 2014, 07:05:49 PM
emailed, this one tested as working too

http://www.scriptbasic.org/download/SB_2.1_RC2_Win.zip

File:     scriba.exe
Size:     507904
MD5:      E2E283CCAE0C493B29634984C302B5FE
Compiled: Sat, Sep 12 2009, 3:19:33  - 32 Bit EXE

Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 07:16:01 PM
Yours worked. STRANGE !!!

C:\SB22\sbcom\sbvb3>scriba COM_VB6_CallBack_Example.sb
obj = 1413952
oCollection = 1414112
Back in script basic Button1_Click arg=21
Back in script basic Button2_Click arg=22
LaunchCallBackForm returned 44
test complete!

C:\SB22\sbcom\sbvb3>

You're using the 2.1 (OLD) version of scriba.exe. I think that was compiled with VC7 or VC9. The SB 2.2 was compiled with VC10 from the Win7 SDK.

C:\SB22\sbcom\sbvb3>scriba -v
ScriptBasic v2.1
Variation >>STANDARD<< build 1
Magic value 859034417
Node size is 16
Extension interface version is 11
Compilation: Sep 11 2009 23:19:32
Executable: C:\SB22\bin\scriba.exe

C:\SB22\sbcom\sbvb3>
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 16, 2014, 07:55:03 PM
My money is on internal structures must have changed offsets from a new pointer added to a structure or something.

Here is the VS2008 crash course video on setup and debugging. Set HD quality for best viewing.

http://youtu.be/ZNiKYCDNqV8

Note that the video capture software did not record the mouse over variable popups for some reason. If you hear me pulling numbers out of thin air, its because a tool tip window was displaying variable values to me on mouse over

ok now I am going to sleep for real this time :)
Title: Re: Couple Api ideas for embedding
Post by: Support on June 16, 2014, 07:59:44 PM
Can you make it work with the current 2.2 version scriba.exe? Tom added a dozen math functions that were stubs in 2.1. There has also been a couple minor bug fixes as well. I really don't want to use 2.1 code knowing the grief I went through getting it resolved.


Great job on the video. You make things look so easy. I will have to play this again more than a couple times to grasp what is like opening a car door to you.  8)
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 17, 2014, 06:37:17 AM
i found the 2.2 source, attached is the COM.dll compatible with v 2.2.

all I had to do is build against its header files instead of the 2.1 ones

I also diffed the headers, I didnt see anything immediately obvious as to why the structure pointer offsets
were changed, but in the debugger I could see they were which is why it was crashing.
Title: Re: Couple Api ideas for embedding
Post by: Support on June 17, 2014, 09:57:57 AM
That solved the problem and it is working fine with Script BASIC 2.2 code base.

Theming would be sweet!

(http://files.allbasic.info/ScriptBasic/SBCOM/sbvb_cb.png)

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

C:\SB22\sbcom\sbvb3>scriba COM_VB6_Callback_Example.sb
obj = 1414352
oCollection = 1414432
Back in script basic Button1_Click arg=21
Back in script basic Button2_Click arg=22
LaunchCallBackForm returned 44
test complete!

C:\SB22\sbcom\sbvb3>scriba -v
ScriptBasic v2.2
Variation >>Windows32<< build 2
Magic value 859001395
Node size is 16
Extension interface version is 11
Compilation: May  3 2014 21:45:37
Executable: C:\SB22\bin\scriba.exe

C:\SB22\sbcom\sbvb3>
Title: Re: Couple Api ideas for embedding
Post by: Support on June 17, 2014, 06:06:01 PM
A bit of progress on the theming front. The new com.dll (SB ext. mod.) isn't hanging when using the scriba.exe.manifest or sbiup.exe (Windows SB + theming support version) but it isn't showing a window either. Returns immediately.


C:\SB22\sbcom\sbvb3>scriba COM_VB6_Callback_Example.sb
obj = 1479888
oCollection = 1479968
LaunchCallBackForm returned 0
test complete!

C:\SB22\sbcom\sbvb3>
Title: Re: Couple Api ideas for embedding
Post by: Support on June 17, 2014, 07:53:47 PM
I was able to get your Script BASIC VB COM callback example running under Windows 7 64 bit.  I also installed Visual Studio 6 for my VB6 install on Windows 7.

Note: regsrv32 must be run as an admin to work.

(http://files.allbasic.info/ScriptBasic/SBCOM/sbvb_cb_w7.png)
Title: Re: Couple Api ideas for embedding
Post by: Support on June 17, 2014, 10:59:27 PM
I was able to get VB themed with a manifest file on XP. It should work for Windows 7 but haven't tried it yet. Using the same manifest with scriba didn't display the form.  :'(

Here is the VB6.EXE.manifest you will need to get VB6 theme support on XP.

Code: [Select]
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    version="6.00.9782.0"
    processorArchitecture="X86"
    name="Visual Basic"
    type="win32"
    />
  <description>Microsoft Corporation VB6</description>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                type="win32"
                name="Microsoft.Windows.Common-Controls"
                version="6.0.0.0"
                processorArchitecture="X86"
                publicKeyToken="6595b64144ccf1df"
                language="*"
             />
        </dependentAssembly>
    </dependency>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                type="win32"
                name="Microsoft.Windows.GdiPlus"
                version="1.0.0.0"
                processorArchitecture="X86"
                publicKeyToken="6595b64144ccf1df"
                language="*"
             />
        </dependentAssembly>
    </dependency>
<!-- Identify the application as DPI-aware: Vista and above -->
  <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
      <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
        <dpiAware>true</dpiAware>
      </asmv3:windowsSettings>
  </asmv3:application>
</assembly>
Title: Re: Couple Api ideas for embedding
Post by: Support on June 18, 2014, 12:13:15 AM
Here is what a VB6 application looks like themed on Windows 7.

CommonControls (Replacement of the MS common controls) (http://www.vbforums.com/showthread.php?698563-CommonControls-(Replacement-of-the-MS-common-controls))

(http://www.vbforums.com/attachment.php?attachmentid=108113&d=1386626689)

I will try to get VB6 theming working on Windows 7 64 bit tomorrow.
Title: Re: Couple Api ideas for embedding
Post by: Support on June 18, 2014, 01:48:51 PM
Poking around there seems to a focused effort on keeping VB Classic alive. I think it's great Dave is showing what the intent of VB was but never embraced. (building COM objects that can be used by other languages)

I'm still trying to get VB6 theming working on Windows 7 and will post something when I get it working. I think creating a current VB6 distributables zip would help this project out a lot. I need to revisit the VB6 controls edition again now that it seems to have purpose to me.

 
Title: Re: Couple Api ideas for embedding
Post by: Support on June 18, 2014, 02:39:39 PM
I was able to find a VB5CCE (Visual BASIC 5 Controls Creation Edition) with help files. You can download it HERE (http://files.allbasic.info/ScriptBasic/SBCOM/VB5_CCE.zip). The manifest file I posted above will work with the VB5CCE version if you rename it to vb5cce.exe.manifest. The conrol edition will let you create standard Windows forms but are saved as a project file and can't be compiled to a .exe.

(http://files.allbasic.info/ScriptBasic/SBCOM/vb5cce.png)
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 18, 2014, 03:38:22 PM
I just did a couple quick tests with vb5 cce since it had been a while.

We can not host usercontrol UIs at the moment, but you can use code in the usercontrol the same as if it were just a standard public class, its just that its UI wont be visible. From the "class" you can then display a traditional form object which can host the UI

In other news i figured out a way for the vb form to pass an arbitrary number of arguments to
the script basic callback, and to let the script basic call back return either a long or string.
that should cover most use needs I think.
Title: Re: Couple Api ideas for embedding
Post by: Support on June 18, 2014, 03:48:30 PM
I wasn't sure what value the VB5CCE version would offer so thanks for clearing that up. Is any of the runtime components of VB5CCE usable for anything? From what I gather I can create a standard VB form, save the it as a project file, load it in standard VB and create a standalone .exe with it. If anything maybe it can be used as an IDE / Debugger of sorts.

Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 18, 2014, 03:56:02 PM
all of the things i did in the vb6 demo can be done from the vb5 cce

the user control will be the class, and it will display the form. same mechanisms at play
Title: Re: Couple Api ideas for embedding
Post by: Support on June 18, 2014, 04:00:17 PM
So are you saying VB5CCE wasn't a waste of time and can be used in the SB VB COM project?

Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 18, 2014, 04:14:01 PM
yup still works fine in vb5cce see attached
Title: Re: Couple Api ideas for embedding
Post by: Support on June 18, 2014, 04:30:07 PM
Very Cool!

I had to register the OCX this time. (no dll)

(http://files.allbasic.info/ScriptBasic/SBCOM/vb5ocx.png)

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

obj = CreateObject("VB5.CCESample")

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" )
   
    retVal = CallByName(obj, "LaunchCallBackForm", vbMethod, 21)
    print "LaunchCallBackForm returned ", retVal, "\n"
   
    ReleaseObject(obj)
    print "test complete!\n"
end if

C:\SB22\sbcom\sbvb4>scriba VB5_Example.sb
obj = 1400632
oCollection = 1406752
Back in script basic Button1_Click arg=21
LaunchCallBackForm returned 22
test complete!

C:\SB22\sbcom\sbvb4>
Title: Re: Couple Api ideas for embedding
Post by: Support on June 18, 2014, 06:06:20 PM
I have been chipping away at getting theming working in XP first and then Win7 afterward. I found this VB6 Manifest Creator code and was able to at least compile it and the form was themed. That lets me know that it's possible and even by me.  8)

(http://files.allbasic.info/ScriptBasic/SBCOM/manifest_creator.png)
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 18, 2014, 06:29:05 PM
nice :)
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 19, 2014, 03:41:42 PM
I was able to get an excel sample working. Had to make a small change to COM.dll to support creating activex exe com objects.

Patch:
https://github.com/dzzie/ScriptBasic_Control/commit/fdfe485bbadc3f676435635fc571687a2b3227a3

full file:
https://raw.githubusercontent.com/dzzie/ScriptBasic_Control/master/engine/COM_Extension_DLL/COM.cpp

Code: [Select]
import com.inc

'on error resume next

filename = "c:\\warehouse.xls"

if FileExists(filename) then
print "File already exists deleting: ", filename,"\n"
delete filename
end if

oExcelApp = CreateObject("Excel.Application")

if oExcelApp = 0 then
    print "Failed to create Excel Object do you have it installed?"
    return
end if

'vbs: Set ExcelWorkbook = ExcelApp.Workbooks.Add
oWorkBook = CallByName(oExcelApp, "Workbooks", vbGet)
oExcelWorkbook = CallByName(oWorkBook, "Add")

'vbs: Set ExcelSheet = ExcelWorkbook.Worksheets(1)
oExcelSheet = CallByName(oExcelWorkbook, "Worksheets", vbGet, 1)

print "Adding cells...\n"

for i=0 to 10
   for j=0 to 10
'vbs: ExcelSheet.Cells(i, j).Value = "test-" & i & "-" & j
oCell = CallByName(oExcelSheet, "Cells", vbGet, i, j)
CallByName(oCell, "Value", vbLet, "test-" & i & "-" & j)
ReleaseObject(oCell)
next
next

print "Saving document as:", filename, "\n"

CallByName(oExcelWorkbook, "SaveAs", vbMethod, filename)
CallByName(oExcelWorkbook, "Close")
CallByName(oExcelApp, "Quit")

print "Releasing objects from memory...\n"

ReleaseObject(oExcelSheet)
ReleaseObject(oExcelWorkbook)
ReleaseObject(oWorkBook)
ReleaseObject(oExcelApp)

print "Script complete!\n"
Title: Re: Couple Api ideas for embedding
Post by: Support on June 19, 2014, 05:52:42 PM
That is very cool Dave. It looks like you're calling another object (Workbooks) with CallByName(), is that correct?

Can you post a compiled COM.dll as I'm still getting my Visual Studio 8 setup for this project?

This Script BASIC VB Classic project keeps getting more interesting by the minute.  8)
Title: Re: Couple Api ideas for embedding
Post by: dzzie on June 19, 2014, 06:38:10 PM
attached is the updated dll for scriba v2.2.

I also added a new export TypeName(obj) which will return the class name of the COM object.
I am pretty much done with another command which will allow you to list the public methods/properties of a given com object
The SBCallBackEx export, usable by VB5/6 UIs now also allows the VB form to call back into script basic function using arbitrary number
of arguments of string or long type, and can handle string or long return values from script basic back to vb

In the excel example, any of the variables startign with o are COM object pointers, there are a bunch of them.

without the dot notation, you have to handle access one step at a time.

so in vbscript the single line:

Set ExcelWorkbook = ExcelApp.Workbooks.Add

Has to be converted out to:

oWorkBook = CallByName(oExcelApp, "Workbooks", vbGet)
oExcelWorkbook = CallByName(oWorkBook, "Add")

To simplify this, I could probably make callbyname parse complex strings and automate these
steps which could potentially reduce it down to a very managable:

oExcelWorkbook = CallByName(oExcelApp, "ExcelApp.Workbooks.Add")

or in more complicated form:

ExcelSheet.Cells(i, j).Value = x



Title: Re: Couple Api ideas for embedding
Post by: Support on June 19, 2014, 07:04:33 PM
Thanks Dave!

I'm installing Office 2010 Pro in my XP VirtualBox so I can try your new COM features with the SB ext. module.

Being able to browse COM objects will be nice. Something to add to the SB debugger your working on possibly.

Title: Re: Couple Api ideas for embedding
Post by: Support on June 19, 2014, 09:54:06 PM
Works fine with Office 2010 Pro on XP.

(http://files.allbasic.info/ScriptBasic/SBCOM/sbvb_excel.png)