Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
475 views
in Technique[技术] by (71.8m points)

vb6 - Trying to call a C DLL from VB. Can't get one of the parameters working

Trying to set up a USB power strip.

Here's the documentation:

Initializes the Power USB API.

Name: InitPowerUSB 

Parameters: model:returns the model number(1:basic, 2:digIO, 3:watchdog, 4:Smart), firmware: returns firmware version in ?.? format in a character string (major revision and minor revision) 

Return: >0 if successful. Returns number of PowerUSB devices connected

C++ Example:

if (!m_pwrUSBInit)
{
    int model; char firmware[8];
    if ((ret=InitPowerUSB(&model, firmware)) > 0)
    {
        m_pwrUSBInit = 1;
        m_numDevices = ret;
    }
}

I have been trying to get this working with my VB6 code for around an hour now with no luck. The program either crashes, displays an error like Bad Calling Dll Convention, type mismatch, et cetera.

Here's what I have:

Public Declare Function InitPowerUSB Lib "PwrUSBDll.dll" (ByRef model As Integer, ByVal firmware As String) As Integer

Dim model As Integer
model = 0

Dim firmware As String
firmware = ""

If (InitPowerUSB(model, firmware)) > 0) Then

EndIf

I have tried changing firmware to byte arrays, byref, string, integer, long, etc. It just doesn't seem to want to run.

Does anyone know of a solution to this problem? Thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I can't answer the rest of your function signature woes since I don't have any documentation for your PwrUSBDll.dll.

However "Bad DLL calling convention" errors generally mean you have a CDecl entrypoint and VB6 can only call those with some help.

There are a couple of fixes.

The obvious one is to modifiy the source and recompile that DLL using StdCall instead.

Another is to create a type library for that DLL, which helps inform VB6 about the issue and resolves it.

Then you have the option of using VB6's undocumented CDecl decorator:

Public Declare Function InitPowerUSB CDecl Lib "PwrUSBDll.dll" ( _
    ByRef model As Integer, _
    ByVal firmware As String) As Integer

However the downside is that this will not work when run within the IDE, nor will it work when compiled to p-code. The p-code interpreter doesn't process this keyword.

So you could just bypass it in IDE runs and supply dummy results for testing, or you can create a small wrapper DLL in VB6 that you separately compile to native code.

Caveats:

For this to solve your problem we'd have to assume you are passing correct data types in that argument list. A C++ int is a VB6 Long. You are probably better off passing a VB6 Byte array ByRef for that char[8] unless this is a Unicode DLL entrypoint. The function return value is also most likely Long.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...