Solved

How to get correct string return from C DLL ?

Posted on 2010-11-12
9
314 Views
Last Modified: 2012-05-10
Hi experts!

I make a call from Vb6 to DLL written in MS C. I get result in sErr without get error, but I can see all message  only in Intermediate windows of Vb6. When I make for example msgbox sErr I get only first letter of whole text. Review pic. To understand better situation.

I have a row sErr = String(255, vbNullChar) which is not seen by the picture, but this doesn’t help.

 Please help – how to get this text in ordinary VB6 string ?

Thanks.

P.S: here you describe what is result of function from C declaration

7.2      GetErrorText()
const char* GetErrorText(int nError) const;

Return: The GetErrorText() function returns a pointer to a character string that contains a printable version of the error indicated by nError.

String-Mistery.png
0
Comment
Question by:dvplayltd
  • 4
  • 2
  • 2
  • +1
9 Comments
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 34122978
VB uses a type of string known as a BSTR.  If you have control over the C Source Code, you want to change that code to return you a BSTR.  Here's an example function:

BSTR __declspec(dllexport) FAR PASCAL GetSomeString( int i )
{
    char* pString = FunctionToGetAString( i );
    return SysAllocStringByteLen( p, strlen( p ) );
}

The VB Declare will look something like this:
Public Function GetSomeString alias GetSomeString_4( I as Integer ) as String
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 34123110
That would work, however since it's returning you a pointer to a string you change the decleration to Long and then you can copy the content into an allocated buffer.

// Usage
Dim pErrString      As Long
pErrString = GetErrorText(0)
Debug.Print PtrToStringAnsi(pErrString)
Private Declare Function GetErrorText Lib "example.dll" ( _

    ByVal nError As Long) As Long



Private Declare Sub RtlMoveMemory Lib "Kernel32.dll" ( _

    ByRef pDest As Any, _

    ByRef pSrc As Any, _

    ByVal ByteLen As Long)

    

Private Declare Function lstrlenA Lib "Kernel32.dll" ( _

    ByVal ptr As Long) As Long

    

Private Function PtrToStringAnsi(ByVal ptr As Long) As String

    Dim Buffer      As String

    Dim cb          As Long

    If ptr = 0 Then

        Exit Function

    End If

    cb = lstrlenA(ptr)

    If cb > 0 Then

        Buffer = String$(cb, vbNullChar)

        RtlMoveMemory ByVal Buffer$, ByVal ptr&, cb

        PtrToStringAnsi = Buffer

    Else

        PtrToStringAnsi = vbNullString

    End If

End Function

Open in new window

0
 

Author Comment

by:dvplayltd
ID: 34123445
To HooKooDooKu

I can’t change source of C DLL, this is hardware card.

To edi1044

Thanks very very much for help. I was sure that I need some think like that, but was not able to write it on my self.
I use you example and found only 1 error – it again return only first letter. But I make a test and find where is problem, but again I can’t solve it, please help if you could.

    cb = lstrlenA(ptr)
    If cb > 0 Then
       Buffer = String$(cb, vbNullChar)

Cb is 1, with immediate windows I set cb=3 and in buffer I see correct first 3 letters of message. Therefor, this      cb = lstrlenA(ptr) do work fine, how to correct it ?

Again thanks!
0
 

Author Comment

by:dvplayltd
ID: 34123516
To edi1044

Hyyym. I found a half of solution – I use Unicode version of drivers. So I change

cb = lstrlenA(ptr)
to
cb = lstrlenW(ptr)

and now I get len of string 14
Real message is:File not found
But I get  F I l e n o t  beacouse it count space also. How to fix this ? Simple by multiply * 2 ?
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 45

Expert Comment

by:aikimark
ID: 34123547
can you pass a byte array instead of a string?
0
 

Author Comment

by:dvplayltd
ID: 34123591
Hyyym. Look pic. Now is same result. Is it possible in this string the separator between real chars to be some bad charter like new row or whatever and I to solve question with just remove it ?
String-Mistery-2.png
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 34123593
Well, if you can't change the DLL, then write your own to be the interface between the DLL and your VB code.  Your VB code calls your C DLL code, which in turn calls the DLL that returns the char*.  Then convert the char* to a BSTR using the sample I listed before.  

I like doing this for any major VB application because it gives you the flexability of doing stuff in VB and C.
0
 
LVL 29

Accepted Solution

by:
nffvrxqgrcfqvvc earned 500 total points
ID: 34123958
If your dealing with a unicode pointer then replace it with the following.
Private Declare Function lstrlenW Lib "Kernel32.dll" ( _

    ByVal ptr As Long) As Long



Private Function PointerToStringUni(ByVal lpPointer As Long) As String

    Dim Buffer()    As Byte

    Dim lpSize      As Long

    

    If lpPointer = 0 Then

        Exit Function

    End If

    

    lpSize = lstrlenW(lpPointer) * 2

    

    If lpSize <> 0 Then

        ReDim Buffer(lpSize) As Byte

        RtlMoveMemory Buffer(0), ByVal lpPointer, lpSize

        PointerToStringUni = Buffer

    Else

        PointerToStringUni = vbNullString

    End If

    

    Erase Buffer

End Function

Open in new window

0
 

Author Closing Comment

by:dvplayltd
ID: 34124012
10x. I make change and now work. You are the great! Thanks !
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now