[Gambas-devel] Re: Gambas and Visual Basic (plain text version)

Jean-Francois Perreault cmcpero at ...28...
Fri Mar 18 17:44:59 CET 2005


Hi,

Richard Stallman wrote:

> As I tried to say before, directly compiling VB source code in Gambas, 
> Java,
> or any other bytecode does not solve the big problems: calls to external
> Windows DLLs, use of ActiveX controls and objects, use of ActiveX 
> automation.
>
> I understand this part, but I disagree with the conclusion. Just
> because this won't solve all the problems is no reason not to do it.
> Solving part of the problem is better than nothing, Every long journey
> starts with a single step. This can be the first step.
>
> I think the ReactOS developers are writing replacements for many Windows
> DLLs. That would be a second step. Eventually we will do it all.
>
> If you do the part of this job that you can straightforwardly do,
> it will be a great start. So how about it?


first , I'd like to say that if gambas is going to be involved in 
running VB code, the only way this should happen would be to 
"re-compile" VB code straight into gambas code , targeting the gambas 
bytecode , isn't an optimal solution because there are "better" bytecode 
for that purpose , while gambas is great, it's internal bytecode wasn't 
necesarily designed for this so if a bytecode was to be targeted , 
parrocode , or the (not as quickly moving as people think target) java, 
are probably better target just because they are more 
general/all-purpose than gambas is (what with being developped 
exclusively for the gambas language)

if it's going to re-interpret vb code into gambas code , every native vb 
function that gambas doesn't have or behave the same as in vb will have 
to be decomposed into simpler gambas functions , not unlike how a C 
compiler decompose each statement into a lot of simpler asm commands (I 
guess)

but that doesn't solve the problem that there are some things gambas 
just can't do

I think this is what the original poster was trying to say , the problem 
with gambas is that it can't directly access arbitrary functions in a 
lib or dll

so the problem isn't that the windows API isn't available on the target 
environment, it's that it's innacessible even if it was available , at 
least in the way vb does it

gambas need components to bridge between system supplied API and gambas 
interpreted code and judging from previous answer on that subject from 
Benoit , at least for now it is impossible to access outside functions 
like VB does

for example ..
VB has the Lib and Alias keywords for use while declaring a function

Lib specifies the dll (or lib if this could work with other OSes) and 
Alias give the name of the function in that dll
a declaration is like this

Declare Function lopen Lib "kernel32" Alias "_lopen" (ByVal IpPathName 
as String, ByVal iReadWrite as long) as Long

it seems that it is the nature of interpreted language to have this 
limitation
PERL , PHP , Python , apparently all need some special code to bridge 
that gap in the intepreter between the system and the running code

so this is why I guess , vb code cannot run 1:1 on gambas , or any other 
interpreted environment , some code might run (pure vb only) but never all

but this might only be true with vb6 , I don't know if vb.net only runs 
inside that .net framework (an interpreter ?)
if it does then I suppose getting that code to run would be the mono 
project's job more that gambas'

but if vb.net code is running inside an interpreter then I suppose this 
mean vb.net also cannot access external dlls without some patchwork code 
? I don't think they would do that because that greatly limit what the 
language can do , maybe some code run natively while some other parts 
run in the .NET interpreter , if that is the case , to run under linux , 
it would be the job of both mono and wine (via winelib) , still not 
gambas' job

it would be great if there was a way to dynamically access functions 
inside external dlls without the need for any special interface code , 
then it could be possible to run vb code in gambas on windows at least

on linux (and macos), it would still be the system's job to supply the 
windows API and other libraries but at least the code could run mostly as-is

the problem with components is that they can only be added to the gambas 
interpreter at the of compilation of the interpreter it self , that make 
adding components without recompiling gambas impossible , if it was 
possible to "plug-in" any component into any live gambas installation , 
then the component could be distributed with the application or 
distribued via a centrallized system not unlike PHP's PEAR and PERL's 
CPAN and others

just that would be a big step forward in programmer (and user) usability

but if that was possible then I guess it would be then possible for the 
gambas interpreter to dynamically generate components based on 
instructions in the running gambas code and then we could have a working 
Lib and Alias keyword for our SUB and FUNCTION

in the case of Declare Function lopen Lib "kernel32" Alias "_lopen" 
(ByVal IpPathName as String, ByVal iReadWrite as long) as Long
the interpreter could just, on the fly generate a kernel32 class module 
with a lopen function , so I guess there is something infeasible about 
this , because that would mean the other interpreted language could work 
without special "components" too .... but still the other interpreters 
allow to install those component after the compilation of the 
interpreter (they are not "built-in" to the interpreter) , so I guess 
the key here would be to generate components , on the fly , at run time 
then reload the interpreter with those new components , or dynamically 
insert them (like kernel modules ?) ?

in any way , I can only come to the conclusion that something in this 
method is not possible , or else there would be no need for CPAN/PEAR 
and the others, I'm sure much better engineers than I, have worked on 
this problem and it must be impossible because of the existance of 
CPAN/PEAR ....

this also points out another problem with gambas , not as pressing , but 
since every lib is going to need a component before it is used , many 
components will be created , at some point it will not be practical for 
all of them to be bundled with the gambas interpreter , so they will 
need to be separate , also to avoid "DLL HELL" problem , a central 
repository will need to be created , and a tool to easily download and 
install individual components on a live gambas installation (even if 
this require recompiling the interpreter) without that , when gambas 
start getting bundled with the major distros you'll have the default 
component installed and if you want more you need to re-install gambas 
by hand , since the user won't bother doing that if it's not easy 
enough, that would mean for gambas programmers that the default 
components are the only components they can use because their audience 
don't have and won't install extra components , this is also why a 
single programmer won't bother make a single-use component for his 
applications , because then his application will only run on his workstation



if creating components on the fly is possible --  if there can be a Lib 
and Alias keywork to FUNCTION in gambas , I suppose the reason it does 
not exist now is that it would not work at all times right now

in the case of Function lopen Lib "kernel32" Alias "_lopen" (ByVal 
IpPathName as String, ByVal iReadWrite as long) as Long

it would be no problem becase all the arguments are ByVal , which is the 
default way gambas passes variables

but for some (many?) function it is not so easy

first some functions require just the pointer to variables so the called 
functions can write to it , there is no ByRef keywork with gambas
also if there was , there is no garantee that the variables are stored 
in a way that the called function expects

(if it wants a CHAR array you can't give it a string (even a native 
gambas string) because those are internally stored as utf-8 while the 
called function is going to expect 1 byte per character ASCII , and 
there is no garantee that strings in gambas are contiguous or 
uncompressed or etc.. we don't know how gambas stores strings (well .. I 
don't) and we can't make assumptions about that, and one thing is sure 
is that however strings are stored it is highly unlikely that the called 
function will know how that strings are stored and how to manipulate them)

assuming native byte arrays are stored the same way they are elsewhere 
we could use that instead , then there would need to be a way to get the 
pointer to that byte array , in VB, if the ByRef keyword didn't exist 
and ByVal was the default way of passing variables  , then the VarPtr() 
function would be used , VarPtr is a function that return the pointer to 
any "standard" variable (there is also StrPtr , that return a pointer to 
the unicode string you ask it and ObjPtr for the pointer to object and 
User Defined Types (another feature I would love to see in gambas , 
making a class is overkill when you want a UDT , how come we don't have 
UDTs ?! that's just weird I can't find a reason why we don't have them ! 
oh well...))

if we had those special function , and assuming that at least native 
byte arrays are stored in memory the same way it is with other languages 
when most API would become accessible

but there is at least another special case that wouldn't work , callbacks
from memory there is this very important windows API that uses callback

Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd 
As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

that function if I remember correctly serves to intercept all events of 
a "window"  the last argument is a pointer to a subroutine

in vb to use that API you have to use the AddressOf function

like this

SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)

AddressOf returns the pointer to the function , now the only way this 
could possibly work in gambas in the dynamically run-time created 
component scenario is if subroutine are stored in memory as machine 
executable code (if I understand correctly a JIT compiler like gambas 
compiles the subroutines and functions into executable at run-time using 
the bytecode , but I don't know if all the code is turned into machine 
code when the program start or just as the code is about to be executed 
(and discarded afterwards or kept in a cache , but not kept in whole in 
memory in a static location)) if it's not possible to give it the 
pointer to the real subroutine then there should be a way to tell the 
interpreter to listen for events at a certain address and when an event 
comes it would then fire the real sub-routine

well anyway , direct "component-less" access to function in arbitrary 
DLLs and libs is certainly #1 in my gambas wishlist , I'd be really 
interested to hear how this could be done or why it's impossible

with that I could even do ioctls and finish my joystick class ! ;)
which btw , can easily handle 500+ events at less then 5% CPU usage on 
an athlon 1800+ and with only 0.002 second latency (only if I use native 
variables however , classes (like string array classes) eat 100% real 
quick (but latency is a bit better however , but at that cpu cost it's 
irrelevent))


I hope to hear some comments on this , from anyone!

--
Jean-Francois Perreault




More information about the Devel mailing list