[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