Board index » delphi » Calling DLL from VB

Calling DLL from VB

This is the firs time I am posting so I hope that it will get though.

     This is an example of the use of string in a Delphi DLL called from VB.

The main points are:

     VB will change a string to a C null terminated string and pass it using the BYVAL reserved
word.

     Delphi DLL must expected a C null terminated string and hence must used PChar as a
parameters.

     VB (from its documentation) cannot used a DLL fuction to return a string from a DLL, so
you have to use a procedure and changed the actual value of the string within the procedure.

     This is an example of that:

     The DLL is a function that test and altered a string to make sure that it is made of  numbers
only (with or without a point). In others words it make sure the data entered is either an integer or
a float. It informs VB whether the string have been changed.

*************************************** VB programm

     The VB form contains one textbox, one command button and one label. The user enters the
data in the textbox. By pressing the command button it calls the DLL which will evaluate if
numbers only have been entered in the textbox.

Option Explicit

Declare Function chiffresslt Lib "d:\data\delphi\nbs6.dll" (ByVal anystring As String, ByVal
onlypoint As Integer) As Integer

Sub Command1_Click ()
Dim somestring As String, thepoint%, realstr%
'thepoint% = 0 = false     That is check if the input is a float
'thepoint% = 1 = true        That is check if the input is an integer
thepoint% = 1
somestring$ = LTrim$(RTrim$((text1.Text)))
realstr% = chiffresslt(somestring$, thepoint%)
somestring$ = Trim$(somestring)
text1.Text = somestring$
label1.Caption = Str(realstr%)
End Sub

****************************************Delphi DLL
library Nbs6;

uses
  sysutils;

{$R *.RES}
function ChiffresSlt(pstr:pchar; OnlyPoint:boolean):integer;export;
var
midstring : string;
i : integer;
chartype:integer;

begin {function}
{if the lenght of string = 0 then exit}

if strlen(pstr)  = 0 then
begin
pstr:= '';
chiffresslt := 1;
exit;
end;
{initialize chiffresslt to true that is = 1}
chiffresslt := 1;
{initialize resulting string to nothing}
midstring := '';

{evaluate each characters}
for i := 0 to (strlen(pstr) - 1) do
begin
chartype := 3;
       if (pstr[i] >= chr(48)) and (pstr[i] <= chr(57)) then
             chartype := 1
         else
                 if (pstr[i] = chr(46)) then
                    begin
                    if onlypoint = false then
                       begin
                       chartype := 2;
                       onlypoint := true;
                       end
                    end
            else
                chiffresslt := 0; {string does not contain only numbers and points}

       case chartype of
       1,2 : midstring := midstring + pstr[i];
end;   {case of}
end;
strpcopy(pstr,midstring);
end; {function}

exports
chiffresSlt index 1;
begin
end.

******************************

I hopes this can help

Marc Charbonneau

 

Re:Calling DLL from VB


Quote
char...@ere.umontreal.ca wrote:

> This is the firs time I am posting so I hope that it will get though.

>      This is an example of the use of string in a Delphi DLL called from VB.

> The main points are:

>      VB will change a string to a C null terminated string and pass it using the BYVAL reserved
> word.

>      Delphi DLL must expected a C null terminated string and hence must used PChar as a
> parameters.

>      VB (from its documentation) cannot used a DLL fuction to return a string from a DLL, so
> you have to use a procedure and changed the actual value of the string within the procedure.

>      This is an example of that:

>      The DLL is a function that test and altered a string to make sure that it is made of  numbers
> only (with or without a point). In others words it make sure the data entered is either an integer or
> a float. It informs VB whether the string have been changed.

> *************************************** VB programm

>      The VB form contains one textbox, one command button and one label. The user enters the
> data in the textbox. By pressing the command button it calls the DLL which will evaluate if
> numbers only have been entered in the textbox.

> Option Explicit

> Declare Function chiffresslt Lib "d:\data\delphi\nbs6.dll" (ByVal anystring As String, ByVal
> onlypoint As Integer) As Integer

> Sub Command1_Click ()
> Dim somestring As String, thepoint%, realstr%
> 'thepoint% = 0 = false     That is check if the input is a float
> 'thepoint% = 1 = true        That is check if the input is an integer
> thepoint% = 1
> somestring$ = LTrim$(RTrim$((text1.Text)))
> realstr% = chiffresslt(somestring$, thepoint%)
> somestring$ = Trim$(somestring)
> text1.Text = somestring$
> label1.Caption = Str(realstr%)
> End Sub

> ****************************************Delphi DLL
> library Nbs6;

> uses
>   sysutils;

> {$R *.RES}
> function ChiffresSlt(pstr:pchar; OnlyPoint:boolean):integer;export;
> var
> midstring : string;
> i : integer;
> chartype:integer;

> begin {function}
> {if the lenght of string = 0 then exit}

> if strlen(pstr)  = 0 then
> begin
> pstr:= '';
> chiffresslt := 1;
> exit;
> end;
> {initialize chiffresslt to true that is = 1}
> chiffresslt := 1;
> {initialize resulting string to nothing}
> midstring := '';

> {evaluate each characters}
> for i := 0 to (strlen(pstr) - 1) do
> begin
> chartype := 3;
>        if (pstr[i] >= chr(48)) and (pstr[i] <= chr(57)) then
>              chartype := 1
>          else
>                  if (pstr[i] = chr(46)) then
>                     begin
>                     if onlypoint = false then
>                        begin
>                        chartype := 2;
>                        onlypoint := true;
>                        end
>                     end
>             else
>                 chiffresslt := 0; {string does not contain only numbers and points}

>        case chartype of
>        1,2 : midstring := midstring + pstr[i];
> end;   {case of}
> end;
> strpcopy(pstr,midstring);
> end; {function}

> exports
> chiffresSlt index 1;
> begin
> end.

> ******************************

> I hopes this can help

> Marc Charbonneau

Thank you for this example but I am sad to report that (at least on my
system) i get a GPF!  I am actually starting to think that there is
something very wrong with my OS (mabye corrupted).  I am running win95,
using delphi developer 2.0 and VB 4.0 (32 bit).  I can not get these
programs to link up!  I have written the simplist of delphi dll's and
called them with the simplest of vb routines and it doesnt ever work!  

For example:

{Delphi}

function IsTrue:Boolean; export;
begin
  result := true;
end;

{vb}
declare function IsTrue lib "c:\windows\system\istrue.dll" as Boolean

// when called, I get bad DLL calling convention //

{Delphi}
function setstr(S:Pchar):Integer;export;
begin
  s:=stralloc(10);
  strCopy(s,'hello,world');
  result :=0;
end;

{vb}
declare function setstr lib "c:\windows\system\setstr.dll" (byval s as
string) as integer

//when called, I get bad DLL calling convention, or my favorite... a GPF
//

I give up.

--
Mike
Micha...@pantheoninc.com

Re:Calling DLL from VB


Quote
Michael Grunder wrote:
> [...]
> Thank you for this example but I am sad to report that (at least on my
> system) i get a GPF!  I am actually starting to think that there is
> something very wrong with my OS (mabye corrupted).  I am running win95,
> using delphi developer 2.0 and VB 4.0 (32 bit).  I can not get these
> programs to link up!  I have written the simplist of delphi dll's and
> called them with the simplest of vb routines and it doesnt ever work!

> For example:

        Well, there's a few errors here.

Quote
> {Delphi}

> function IsTrue:Boolean; export;

        You're doing D2, right? Probably you need stdcall here in place
of export. (See the docs on the difference between stdcall, cdecl, etc.)
        ALSO: are you certain that VB and Delphi are using Boolean variables
of the same size? I'd check the size of a VB Boolean and then make certain
to use the right Delphi Boolean (there's WordBool, etc). Or just use integers.

Quote
> begin
>   result := true;
> end;

> {vb}
> declare function IsTrue lib "c:\windows\system\istrue.dll" as Boolean

> // when called, I get bad DLL calling convention //

> {Delphi}
> function setstr(S:Pchar):Integer;export;
> begin
>   s:=stralloc(10);
>   strCopy(s,'hello,world');

        Once you get the calling convention straight this could very well
GPF on you. You're allocating 10 bytes for s and then copying 11 or 12 bytes
there. Read the docs on StrCopy - you need stralloc(12) here.
        But worse, if you''re going to be caling this from VB there's no
way it's going to work. The stralloc changes the value of S. Maybe in
VB you have a string stored at location 0012:0042. You pass the 0012:0042
to the dll, the dll allocates 12 bytes somewhere else, then copies the
string to the somewhere else. VB looks at 0012:0042 and doesn't find
anything there that wasn't there before.

        Once you get the calling convention straight you need to
omit the stralloc in the dll. Then in VB you dim s as string*12 and
pass s to the dll function. You've already allocated memory in VB,
now the dll will copy 'hello,world' to that location and VB will
know where to find it.

Quote
>   result :=0;
> end;

> {vb}
> declare function setstr lib "c:\windows\system\setstr.dll" (byval s as
> string) as integer
>    SizeOf(integer)=4 in D2. Presumably an integer takes 4 bytes in

VB 4 as well, but it couldn't hurt to check - if an integer were still
2 bytes in VB 4 then this would be another GPF.

Quote
> //when called, I get bad DLL calling convention, or my favorite... a GPF
> //

> I give up.

        Don't do that. It's actually possible to figure out how these things
work, honest.

--
David Ullrich

?his ?s ?avid ?llrich's ?ig ?ile
(Someone undeleted it for me...)

Re:Calling DLL from VB


Quote
Michael Grunder wrote:

> char...@ere.umontreal.ca wrote:

> > This is the firs time I am posting so I hope that it will get though.

> >      This is an example of the use of string in a Delphi DLL called from VB.

> > The main points are:

> >      VB will change a string to a C null terminated string and pass it using the BYVAL reserved
> > word.

> >      Delphi DLL must expected a C null terminated string and hence must used PChar as a
> > parameters.

> >      VB (from its documentation) cannot used a DLL fuction to return a string from a DLL, so
> > you have to use a procedure and changed the actual value of the string within the procedure.

> >      This is an example of that:

> >      The DLL is a function that test and altered a string to make sure that it is made of  numbers
> > only (with or without a point). In others words it make sure the data entered is either an integer or
> > a float. It informs VB whether the string have been changed.

> > *************************************** VB programm

> >      The VB form contains one textbox, one command button and one label. The user enters the
> > data in the textbox. By pressing the command button it calls the DLL which will evaluate if
> > numbers only have been entered in the textbox.

> > Option Explicit

> > Declare Function chiffresslt Lib "d:\data\delphi\nbs6.dll" (ByVal anystring As String, ByVal
> > onlypoint As Integer) As Integer

> > Sub Command1_Click ()
> > Dim somestring As String, thepoint%, realstr%
> > 'thepoint% = 0 = false     That is check if the input is a float
> > 'thepoint% = 1 = true        That is check if the input is an integer
> > thepoint% = 1
> > somestring$ = LTrim$(RTrim$((text1.Text)))
> > realstr% = chiffresslt(somestring$, thepoint%)
> > somestring$ = Trim$(somestring)
> > text1.Text = somestring$
> > label1.Caption = Str(realstr%)
> > End Sub

> > ****************************************Delphi DLL
> > library Nbs6;

> > uses
> >   sysutils;

> > {$R *.RES}
> > function ChiffresSlt(pstr:pchar; OnlyPoint:boolean):integer;export;
> > var
> > midstring : string;
> > i : integer;
> > chartype:integer;

> > begin {function}
> > {if the lenght of string = 0 then exit}

> > if strlen(pstr)  = 0 then
> > begin
> > pstr:= '';
> > chiffresslt := 1;
> > exit;
> > end;
> > {initialize chiffresslt to true that is = 1}
> > chiffresslt := 1;
> > {initialize resulting string to nothing}
> > midstring := '';

> > {evaluate each characters}
> > for i := 0 to (strlen(pstr) - 1) do
> > begin
> > chartype := 3;
> >        if (pstri >= chr(48)) and (pstri <= chr(57)) then
> >              chartype := 1
> >          else
> >                  if (pstri = chr(46)) then
> >                     begin
> >                     if onlypoint = false then
> >                        begin
> >                        chartype := 2;
> >                        onlypoint := true;
> >                        end
> >                     end
> >             else
> >                 chiffresslt := 0; {string does not contain only numbers and points}

> >        case chartype of
> >        1,2 : midstring := midstring + pstri;
> > end;   {case of}
> > end;
> > strpcopy(pstr,midstring);
> > end; {function}

> > exports
> > chiffresSlt index 1;
> > begin
> > end.

> > ******************************

> > I hopes this can help

> > Marc Charbonneau

> Thank you for this example but I am sad to report that (at least on my
> system) i get a GPF!  I am actually starting to think that there is
> something very wrong with my OS (mabye corrupted).  I am running win95,
> using delphi developer 2.0 and VB 4.0 (32 bit).  I can not get these
> programs to link up!  I have written the simplist of delphi dll's and
> called them with the simplest of vb routines and it doesnt ever work!

> For example:

> {Delphi}

> function IsTrue:Boolean; export;
> begin
>   result := true;
> end;

> {vb}
> declare function IsTrue lib "c:\windows\system\istrue.dll" as Boolean

> // when called, I get bad DLL calling convention //

> {Delphi}
> function setstr(S:Pchar):Integer;export;
> begin
>   s:=stralloc(10);
>   strCopy(s,'hello,world');
>   result :=0;
> end;

> {vb}
> declare function setstr lib "c:\windows\system\setstr.dll" (byval s as
> string) as integer

> //when called, I get bad DLL calling convention, or my favorite... a GPF
> //

> I give up.

> --
> Mike
> Micha...@pantheoninc.com

If all else fails, you might try the Delphi2 help; look under Calling Convention.

I believe that VB4 is supposed to conform to the Win95 standard for function
calling -- stdcall. I think, as well, that Delphi2, by default, uses the Register
calling convention. Delphi's default can be changed with a directive -- StdCall --
I don't believe VB's can.

Then there are the data type compatibility subtleties, e.g., no long int in VB, and
of course, the famous string question (which has become a lot easier to handle in
Delphi2.)

...edn <ni...@mail.cibc.com>

Re:Calling DLL from VB


Quote
Ed Nixon wrote:

> Michael Grunder wrote:

> > char...@ere.umontreal.ca wrote:

> > > This is the firs time I am posting so I hope that it will get though.

> > >      This is an example of the use of string in a Delphi DLL called from VB.

> > > The main points are:

> > >      VB will change a string to a C null terminated string and pass it using the BYVAL reserved
> > > word.

> > >      Delphi DLL must expected a C null terminated string and hence must used PChar as a
> > > parameters.

> > >      VB (from its documentation) cannot used a DLL fuction to return a string from a DLL, so
> > > you have to use a procedure and changed the actual value of the string within the procedure.

> > >      This is an example of that:

> > >      The DLL is a function that test and altered a string to make sure that it is made of  numbers
> > > only (with or without a point). In others words it make sure the data entered is either an integer or
> > > a float. It informs VB whether the string have been changed.

> > > *************************************** VB programm

> > >      The VB form contains one textbox, one command button and one label. The user enters the
> > > data in the textbox. By pressing the command button it calls the DLL which will evaluate if
> > > numbers only have been entered in the textbox.

> > > Option Explicit

> > > Declare Function chiffresslt Lib "d:\data\delphi\nbs6.dll" (ByVal anystring As String, ByVal
> > > onlypoint As Integer) As Integer

> > > Sub Command1_Click ()
> > > Dim somestring As String, thepoint%, realstr%
> > > 'thepoint% = 0 = false     That is check if the input is a float
> > > 'thepoint% = 1 = true        That is check if the input is an integer
> > > thepoint% = 1
> > > somestring$ = LTrim$(RTrim$((text1.Text)))
> > > realstr% = chiffresslt(somestring$, thepoint%)
> > > somestring$ = Trim$(somestring)
> > > text1.Text = somestring$
> > > label1.Caption = Str(realstr%)
> > > End Sub

> > > ****************************************Delphi DLL
> > > library Nbs6;

> > > uses
> > >   sysutils;

> > > {$R *.RES}
> > > function ChiffresSlt(pstr:pchar; OnlyPoint:boolean):integer;export;
> > > var
> > > midstring : string;
> > > i : integer;
> > > chartype:integer;

> > > begin {function}
> > > {if the lenght of string = 0 then exit}

> > > if strlen(pstr)  = 0 then
> > > begin
> > > pstr:= '';
> > > chiffresslt := 1;
> > > exit;
> > > end;
> > > {initialize chiffresslt to true that is = 1}
> > > chiffresslt := 1;
> > > {initialize resulting string to nothing}
> > > midstring := '';

> > > {evaluate each characters}
> > > for i := 0 to (strlen(pstr) - 1) do
> > > begin
> > > chartype := 3;
> > >        if (pstri >= chr(48)) and (pstri <= chr(57)) then
> > >              chartype := 1
> > >          else
> > >                  if (pstri = chr(46)) then
> > >                     begin
> > >                     if onlypoint = false then
> > >                        begin
> > >                        chartype := 2;
> > >                        onlypoint := true;
> > >                        end
> > >                     end
> > >             else
> > >                 chiffresslt := 0; {string does not contain only numbers and points}

> > >        case chartype of
> > >        1,2 : midstring := midstring + pstri;
> > > end;   {case of}
> > > end;
> > > strpcopy(pstr,midstring);
> > > end; {function}

> > > exports
> > > chiffresSlt index 1;
> > > begin
> > > end.

> > > ******************************

> > > I hopes this can help

> > > Marc Charbonneau

> > Thank you for this example but I am sad to report that (at least on my
> > system) i get a GPF!  I am actually starting to think that there is
> > something very wrong with my OS (mabye corrupted).  I am running win95,
> > using delphi developer 2.0 and VB 4.0 (32 bit).  I can not get these
> > programs to link up!  I have written the simplist of delphi dll's and
> > called them with the simplest of vb routines and it doesnt ever work!

> > For example:

> > {Delphi}

> > function IsTrue:Boolean; export;
> > begin
> >   result := true;
> > end;

> > {vb}
> > declare function IsTrue lib "c:\windows\system\istrue.dll" as Boolean

> > // when called, I get bad DLL calling convention //

> > {Delphi}
> > function setstr(S:Pchar):Integer;export;
> > begin
> >   s:=stralloc(10);
> >   strCopy(s,'hello,world');
> >   result :=0;
> > end;

> > {vb}
> > declare function setstr lib "c:\windows\system\setstr.dll" (byval s as
> > string) as integer

> > //when called, I get bad DLL calling convention, or my favorite... a GPF
> > //

> > I give up.

> > --
> > Mike
> > Micha...@pantheoninc.com

> If all else fails, you might try the Delphi2 help; look under Calling Convention.

> I believe that VB4 is supposed to conform to the Win95 standard for function
> calling -- stdcall. I think, as well, that Delphi2, by default, uses the Register
> calling convention. Delphi's default can be changed with a directive -- StdCall --
> I don't believe VB's can.

> Then there are the data type compatibility subtleties, e.g., no long int in VB, and
> of course, the famous string question (which has become a lot easier to handle in
> Delphi2.)

> ...edn <ni...@mail.cibc.com>

Thanks, the stdcall worked :)

--
Mike
Micha...@pantheoninc.com

Re:Calling DLL from VB


Quote
Ed Nixon <ni...@mail.cibc.com> wrote:
>Then there are the data type compatibility subtleties, e.g., no long int in VB, and
>of course, the famous string question (which has become a lot easier to handle in
>Delphi2.)

No long integer in VB? There most certainly is. It's LONG in BASIC,
not longint.  There's no DWORD, but then again, there isn't  in D1
either.

JE McTaggart
t...@iguana.ruralnet.net

Other Threads