Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

How to get correct string return from C DLL ?

Posted on 2010-11-12
9
Medium Priority
?
327 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

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 46

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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
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…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

773 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