[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.vb.general.discussion

Help Declare Function in VB6 for function in a C DLL

Mike Larson

9/15/2011 2:00:00 PM

Hello,

I am trying to use a DLL provided by a hardware/software manufacturer
in VB6. The manufacture has not provided example files for VB6 (only
for VS.NET version) and I would have to pay them to create these
files.

My problem is that they have a function in the DLL I want to use but I
can't seem to declare it correctly in my VB6 module, I keep getting a
"Bad DLL Calling Convention" error.

Here is the function from the header file

DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
*typeSupport = NULL);

My first shot at the Declare statement doesn't work.

Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
As Boolean


How would I form the correct Declare Function statement in the VB6
module?

Thanks for any help!

Mike
32 Answers

Dee Earley

9/15/2011 2:09:00 PM

0

On 15/09/2011 15:00, Mike wrote:
> Hello,
>
> I am trying to use a DLL provided by a hardware/software manufacturer
> in VB6. The manufacture has not provided example files for VB6 (only
> for VS.NET version) and I would have to pay them to create these
> files.
>
> My problem is that they have a function in the DLL I want to use but I
> can't seem to declare it correctly in my VB6 module, I keep getting a
> "Bad DLL Calling Convention" error.
>
> Here is the function from the header file
>
> DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
> *typeSupport = NULL);
>
> My first shot at the Declare statement doesn't work.
>
> Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
> voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
> As Boolean
>
> How would I form the correct Declare Function statement in the VB6
> module?

The DLL is most likely written to use the CDECL calling convention which
you can't (easily) call from VB.
If you have the code to the DLL, you could convert them to StdCall or
write a small wrapper DLL.

(Note that there are ways to make CDECL calls in VB6 but I;ve never used
any myself.)

--
Dee Earley (dee.earley@icode.co.uk)
i-Catcher Development Team
http://www.icode.co.uk...

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)

Tom Shelton

9/15/2011 2:46:00 PM

0

Mike formulated the question :
> Hello,
>
> I am trying to use a DLL provided by a hardware/software manufacturer
> in VB6. The manufacture has not provided example files for VB6 (only
> for VS.NET version) and I would have to pay them to create these
> files.
>
> My problem is that they have a function in the DLL I want to use but I
> can't seem to declare it correctly in my VB6 module, I keep getting a
> "Bad DLL Calling Convention" error.
>
> Here is the function from the header file
>
> DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
> *typeSupport = NULL);
>
> My first shot at the Declare statement doesn't work.
>
> Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
> voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
> As Boolean
>

I might change the return value to Long rather than Boolean and try
that first... The BOOL type is usually a typedef for int, which is
32-bit and the VB6 size is 16-bit internally. It's possible, but not
likely that there is a stack imbalance going on here?

Having the definition of DEMO_API or a look at the .net version of the
declare would clear this up a bit - because the likely answer is as
Deanna indicated. C++ will default to cdecl - and vb6 doesn't handle
that calling convention natively.

If it is the case that the call is cdecl, than Mayayana might be able
to help you out here with some code to wrap the call. There is a class
that he was using to make some of these types of calls a while back...

--
Tom Shelton


Mike Larson

9/15/2011 3:22:00 PM

0

Thanks for the replies.

DEMO_API is as follows

#define DEMO_API __declspec(dllexport)

DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
*typeSupport = NULL);

One thing I notice now is that the prototypes in the .h file don't use
_stdcall.



The source file that was available was written in C# (i think). It's
usages of the function is :

public unsafe static extern bool GetVoltage(UInt32 voltType,
float* retval, UInt32* typeSupport);

I have another DLL I created that I can use to make a wrapper, but I
was hoping for the direct approach.

Thanks.

Mike


On Sep 15, 9:45 am, Tom Shelton <tom_shel...@comcast.invalid> wrote:
> Mike formulated the question :
>
>
>
>
>
>
>
>
>
> > Hello,
>
> > I am trying to use a DLL provided by a hardware/software manufacturer
> > in VB6.  The manufacture has not provided example files for VB6 (only
> > for VS.NET version) and I would have to pay them to create these
> > files.
>
> > My problem is that they have a function in the DLL I want to use but I
> > can't seem to declare it correctly in my VB6 module, I keep getting a
> > "Bad DLL Calling Convention" error.
>
> > Here is the function from the header file
>
> > DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
> > *typeSupport = NULL);
>
> > My first shot at the Declare statement doesn't work.
>
> > Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
> > voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
> > As Boolean
>
> I might change the return value to Long rather than Boolean and try
> that first...  The BOOL type is usually a typedef for int, which is
> 32-bit and the VB6 size is 16-bit internally.   It's possible, but not
> likely that there is a stack imbalance going on here?
>
> Having the definition of DEMO_API or a look at the .net version of the
> declare would clear this up a bit - because the likely answer is as
> Deanna indicated.  C++ will default to cdecl - and vb6 doesn't handle
> that calling convention natively.
>
> If it is the case that the call is cdecl, than Mayayana might be able
> to help you out here with some code to wrap the call.  There is a class
> that he was using to make some of these types of calls a while back...
>
> --
> Tom Shelton

Jim Mack

9/15/2011 3:22:00 PM

0

Tom Shelton wrote:
> Mike formulated the question :
>>
>> Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
>> voltType As Long, ByRef retval As Single, ByRef typeSupport As
>> Long) As Boolean
>>
>
> I might change the return value to Long rather than Boolean and try
> that first... The BOOL type is usually a typedef for int, which is
> 32-bit and the VB6 size is 16-bit internally. It's possible, but
> not likely that there is a stack imbalance going on here?

There's a good reason to change the Declare from Boolean to Long, but
it isn't the stack, which is always dword-aligned in Win32. It's that
API 'bool' and VB Boolean have different signs. This can lead to logic
problems.

The larger issue is almost certainly cdecl vs stdcall.

--
Jim Mack
Twisted tees at http://www.cafepress.c...
"We sew confusion"

Tom Shelton

9/15/2011 4:10:00 PM

0

Mike laid this down on his screen :
> Thanks for the replies.
>
> DEMO_API is as follows
>
> #define DEMO_API __declspec(dllexport)
>
> DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
> *typeSupport = NULL);
>
> One thing I notice now is that the prototypes in the .h file don't use
> _stdcall.
>
>
>
> The source file that was available was written in C# (i think). It's
> usages of the function is :
>
> public unsafe static extern bool GetVoltage(UInt32 voltType,
> float* retval, UInt32* typeSupport);
>
> I have another DLL I created that I can use to make a wrapper, but I
> was hoping for the direct approach.
>
> Thanks.
>
> Mike
>

Did you try changing the return type in your declaration?

Based on that C# declaration - I would have to assume that it is
_stdcall (mosly likely it is set at the project level, and not in the
headers). _stdcall is the default even in .NET - if you want to call
cdecl then you have to specify it.

Maybe an example of your calling code would be appropriate as well...

--
Tom Shelton


Mike Larson

9/15/2011 5:00:00 PM

0

OK. Here it all is. I did change the function type in the VB6
declare statement to Long with no affect.

From the supplied header file for the DLL

DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
*typeSupport = NULL);

In my VB6 Module

Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
As Long

In my VB6 form

Private Sub Command3_Click()

Dim sng_retval As Single
Dim lng_typeSupport As Long

Form1.Text3.Text = Format(SusiHWMGetVoltage(0, sng_retval,
lng_typeSupport))

Form1.Text3.Text = Form1.Text3.Text & ", " & sng_retval & ", " &
lng_typeSupport

End Sub

When the button is clicked and the program tries to make the call to
the DLL I get the "Bad DLL calling convention" error.


I will add this also. Other more simple function in the DLL are
working in my VB6 app.
From the header file
DEMO_API BOOL DemoDllInit();

In my module :
Public Declare Function DemoDllInit Lib "C:\MyDemo\Demo.dll" () As
Boolean

In the Form
Private Sub Command1_Click()

Form1.Text1.Text = Format(DemoDllInit)

End Sub

When the button is clicked the text box is filled with "True"


Thanks again all!

Mike



On Sep 15, 11:09 am, Tom Shelton <tom_shel...@comcast.invalid> wrote:
> Mike laid this down on his screen :
>
>
>
>
>
>
>
>
>
> > Thanks for the replies.
>
> > DEMO_API is as follows
>
> > #define DEMO_API __declspec(dllexport)
>
> > DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
> > *typeSupport = NULL);
>
> > One thing I notice now is that the prototypes in the .h file don't use
> > _stdcall.
>
> > The source file that was available was written in C# (i think).  It's
> > usages of the function is :
>
> >         public unsafe static extern bool GetVoltage(UInt32 voltType,
> > float* retval, UInt32* typeSupport);
>
> > I have another DLL I created that I can use to make a wrapper, but I
> > was hoping for the direct approach.
>
> > Thanks.
>
> > Mike
>
> Did you try changing the return type in your declaration?
>
> Based on that C# declaration - I would have to assume that it is
> _stdcall (mosly likely it is set at the project level, and not in the
> headers).  _stdcall is the default even in .NET - if you want to call
> cdecl then you have to specify it.
>
> Maybe an example of your calling code would be appropriate as well...
>
> --
> Tom Shelton

Tom Shelton

9/15/2011 5:21:00 PM

0

Mike submitted this idea :
> OK. Here it all is. I did change the function type in the VB6
> declare statement to Long with no affect.
>
> From the supplied header file for the DLL
>
> DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
> *typeSupport = NULL);
>
> In my VB6 Module
>
> Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
> voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
> As Long
>
> In my VB6 form
>
> Private Sub Command3_Click()
>
> Dim sng_retval As Single
> Dim lng_typeSupport As Long
>


Ok... I think the problem is your call... In the original c
delcaration, the typeSupport parameter is set to a default of NULL
basically, making it an optional parameter.

Your call is essentially passing a pointer to a value that contains 0 -
when it should be passing a null pointer. Try changing the call to:

Form1.Text3.Text = Format(SusiHWMGetVoltage(0, sng_retval, ByVal 0&))

--
Tom Shelton


Karl E. Peterson

9/15/2011 5:26:00 PM

0

It happens that Mike formulated :
> OK. Here it all is. I did change the function type in the VB6
> declare statement to Long with no affect.
>
> From the supplied header file for the DLL
>
> DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
> *typeSupport = NULL);
>
> In my VB6 Module
>
> Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
> voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
> As Long

Do you know for sure the retval paramater is 4-bytes? Might want to
try it As Double. It's very uncommon usage, but...

I have never liked putting paths in the declares, either.

Niether of the above are likely sources of the error, though.

--
..NET: It's About Trust!
http://vfre...


Karl E. Peterson

9/15/2011 5:28:00 PM

0

After serious thinking Tom Shelton wrote :
> Mike submitted this idea :
>> OK. Here it all is. I did change the function type in the VB6
>> declare statement to Long with no affect.
>>
>> From the supplied header file for the DLL
>>
>> DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
>> *typeSupport = NULL);
>>
>> In my VB6 Module
>>
>> Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
>> voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
>> As Long
>>
>> In my VB6 form
>>
>> Private Sub Command3_Click()
>>
>> Dim sng_retval As Single
>> Dim lng_typeSupport As Long
>>
>
>
> Ok... I think the problem is your call... In the original c delcaration, the
> typeSupport parameter is set to a default of NULL basically, making it an
> optional parameter.
>
> Your call is essentially passing a pointer to a value that contains 0 - when
> it should be passing a null pointer. Try changing the call to:
>
> Form1.Text3.Text = Format(SusiHWMGetVoltage(0, sng_retval, ByVal 0&))

Interesting thought! Could be...

--
..NET: It's About Trust!
http://vfre...


Tom Shelton

9/15/2011 5:33:00 PM

0

Karl E. Peterson formulated the question :
> After serious thinking Tom Shelton wrote :
>> Mike submitted this idea :
>>> OK. Here it all is. I did change the function type in the VB6
>>> declare statement to Long with no affect.
>>>
>>> From the supplied header file for the DLL
>>>
>>> DEMO_API BOOL GetVoltage(DWORD voltType, float *retval, DWORD
>>> *typeSupport = NULL);
>>>
>>> In my VB6 Module
>>>
>>> Public Declare Function GetVoltage Lib "C:\MyDemo\Demo.dll" (ByVal
>>> voltType As Long, ByRef retval As Single, ByRef typeSupport As Long)
>>> As Long
>>>
>>> In my VB6 form
>>>
>>> Private Sub Command3_Click()
>>>
>>> Dim sng_retval As Single
>>> Dim lng_typeSupport As Long
>>>
>>
>>
>> Ok... I think the problem is your call... In the original c delcaration,
>> the typeSupport parameter is set to a default of NULL basically, making it
>> an optional parameter.
>>
>> Your call is essentially passing a pointer to a value that contains 0 -
>> when it should be passing a null pointer. Try changing the call to:
>>
>> Form1.Text3.Text = Format(SusiHWMGetVoltage(0, sng_retval, ByVal 0&))
>
> Interesting thought! Could be...

Been a while since I've used vb6 - but I remember this particular error
being a bit generic.

--
Tom Shelton