Solved

How to get correct string return from C DLL ?

Posted on 2010-11-12
9
322 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: 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!

 

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

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

When trying to find the cause of a problem in VBA or VB6 it's often valuable to know what procedures were executed prior to the error. You can use the Call Stack for that but it is often inadequate because it may show procedures you aren't intereste…
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…
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…
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…

756 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