Solved

How to get correct string return from C DLL ?

Posted on 2010-11-12
9
320 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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 

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
 
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

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Vb.net 2008 2 59
Excel object stays open 19 73
Macro which automatically sends attachment to Outlook 14 69
I need help embedding an image as HTML in my vb.net application 3 64
There are many ways to remove duplicate entries in an SQL or Access database. Most make you temporarily insert an ID field, make a temp table and copy data back and forth, and/or are slow. Here is an easy way in VB6 using ADO to remove duplicate row…
Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
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…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

808 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