[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 466
  • Last Modified:

Convert C long to VB string

I need to convert a C long to VB string. I am totally ignorant to C so I'm going to need some hand holding. Any help would be appreciated.

T.I.A

ampapa,
0
ampapa
Asked:
ampapa
  • 12
  • 7
  • 6
  • +2
2 Solutions
 
Erick37Commented:
You want to convert a number returned from a C DLL into a VB string representation?  Can you provide specifics?

0
 
Mikal613Commented:
from long to string in VB

dim Fun as String
dim Lng as long

lng = 23
Fun = CStr(lng)
0
 
ampapaAuthor Commented:
This is currently the function that I am using.

Public Function EnumAppsCallback(laddr As Long, ByVal lParam&) As Integer
'Copy C string to B string
wLen% = EntVBGetCStrLen(laddr&)
szapp$ = Space(wLen%)
ret% = EntVBCopyStr(szapp$, laddr&, wLen%)
If UCase(szapp$) <> "DEFAULT" Or UCase(szapp$) <> "default" Then
'ret% = MsgBox("Application: " & szapp$)
Debug.Print szapp$
End If
EnumAppsCallback% = 0 'continue enumeration
End Function

I don't know what the function EntVBGetCStrLen() does? I'm guessing it does the conversion, but that is what crashes the application. If I dubug and print the variable laddr this is what I get becuase it's a callback.

Public Function EnumAppsCallback(laddr As Long, ByVal lParam&) As Integer
Debug.Print laddr
EnumAppsCallback% = 0 'continue enumeration
End Function

 1634100580
 1635416688
 1852140642
 1919906931
 1397313601


0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
ampapaAuthor Commented:
If trying to use the CSTR() function I get a runtime error 6, overflow.

wLen% = cstr(laddr&)
0
 
Mikal613Commented:
dim Wlen as variant
wLen = cVar(laddr)
0
 
PrestaulCommented:
Are you working in VB or are you working in C?  If you are working in C then are you trying to convert a long to a BStr???  VB uses BStrs to store strings and you can use the same structure in C but if this is the case you should post this question in a C forum.  Try this in C:

_bstr_t B;
long L=45;
B = _bstr_t(L);

No promises, I haven't touched this in a while.  If it doesn't do what you want and you are using C or C++ then try posting in the C forum.
0
 
ampapaAuthor Commented:
I'm still getting a runtime error 6, overflow.

So, what exactly is going on with these 2 functions above?

EntVBGetCStrLen(laddr&)
EntVBCopyStr(szapp$, laddr&, wLen%)
0
 
ampapaAuthor Commented:
I'm working in VB but I think the 2 functions are written in C?
0
 
PrestaulCommented:
Do you have the declarations for the 2 functions?
0
 
ampapaAuthor Commented:
This is what I've got from a "toolkit" I hope it helps.

Hyperion Enterprise API Reference
EntVBGetCStrLen( ) - Get Length of C-string
This function is for Visual Basic only. Some callback functions are passed an
argument which is the address of a C-style string. In Visual Basic the callback
argument function type is long. You can use EntVBGetCStrLen( ) and
EntVBCopyStr( ) to convert the long argument to a Visual Basic string.
You can call EntVBGetCstrLen( ) to get the length of the string, allocate a Visual
Basic string equal to the same length, and call EntVBCopyStr( ) to copy the
C-style string into the Visual Basic string. The function EntVBCopyStr( ) is a
clone of the of EntVBCopyData. )
Advanced Functions
Use this format:
Declare Function EntVBGetCStrLen Lib "heaccess.dll" Alias
"EntVBGetCStrLen@4" (ByVal lAddr As Long) As Integer
where lAddr is the address of the C-style string.


EntVBCopyData( ) - Copy Data
This function is intended for Visual Basic only. The arguments for some callback
functions are actually the address of a structure (user-defined type). If your
callback function declares the argument as type long, you can use
EntVBCopyData( ) to copy that structure into a Visual Basic variable of the correct
type so that you can use it.
Use this Format:
Declare Function EntVBCopyData Lib "heaccess.dll" Alias
"_EntVBCopyData@12" (Dest As Any, ByVal lAddr As Long, ByVal
wLen As Integer) As Integer
Variable Description
Dest The destination buffer
lAddr The address of the source to copy
wLen The length to copy
0
 
zzzzzoocCommented:
The below method should work. You may need to change the W (of the function declarations) to A for whether or not you're dealing with unicode.

Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyW" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenW" (ByVal lpString As Long) As Long
Private Sub Form_Load()
    Dim strA As String, lngPtr As Long
    Dim strB As String, intLen As Integer
    'test source
    strA = "test"
    'this will be our long pointer of strA
    lngPtr = StrPtr(strA)
    'get length of lngPtr
    intLen = lstrlen(lngPtr)
    'create buffer
    strB = String(intLen, vbNullChar)
    'copy source into strB
    lstrcpy ByVal StrPtr(strB), ByVal lngPtr
    'check strB
    MsgBox strB
End Sub

Either this or CopyMemory().
0
 
ampapaAuthor Commented:
zzzzzooc,

Thanks for the example. your source doesn't crash the app but the results aren't what I expected? It's similar when changing the Declarationfs from W to A. I guess that could be because the functions do more than convert a C long to a string?

???????1
??      
??      
???????1  


I don't understand what you meant by "Either this or CopyMemory()."?
0
 
PrestaulCommented:
His code is using two APIs designed for copying strings.  In reality all that they are doing is copying data from one location in memory to another.  CopyMemory is another API which will copy data from any memory location to another regardless of what is there or how it is formatted or whether or not that memory belongs to your app.  I think that if the behavior of his code above is not what you want then the your functions are doing more than they claim and you probably need to figure out how to make them work.  The documentation you showed us above is pretty crappy...  Can you find out anything more from HE or did they provide any sample code that might help things make sense?  Do you have any sample input and output from those functions that may help?
0
 
zzzzzoocCommented:
Doh. I didn't get a notification for your reply.. only got Prest's.

>>I don't understand what you meant by "Either this or CopyMemory()."?
Exactly as Prest mentioned.

>>???????1
Does the copied string show as "????"? If it does, you may only need to convert it to unicode. Since VB stores the strings in unicode, when I copied from one to the other (via it's pointer), it did not require conversion because it was already in unicode.

(prior copying)
strB = StrConv(strB, vbUnicode)

0
 
ampapaAuthor Commented:
I agree "crappy" is being nice though... Most of this was written in C and VB is just something they threw together. I've got a "Toolkit" book (450 pgs.) full of such "crappy" examples and partial codings that bomb without fail.

The callback function is literally just called by supplying the long and lparam as Isupplied above. So, it's as bare bones as I could get it and still it won't work... wacked!

Still no go zzzzzooc, when I step through the code i get different data than when I just run the function then I got blank data. This is what I get when stepping through the code.

???r
???r
???r
???r

0
 
PrestaulCommented:
With what input?  Where is your "C-Style" string coming from and what is in it that provides such an output?  And is that the output from your functions or from z's code?
0
 
ampapaAuthor Commented:
This is what I thought was the "C-Style" string from the below function.

 1634100580
 1635416688
 1852140642
 1919906931
 1397313601

Public Function EnumAppsCallback(laddr As Long, ByVal lParam&) As Integer
Debug.Print laddr
EnumAppsCallback% = 0 'continue enumeration
End Function

This is the function that uses the callback, that's all there is.

Declare Function HypEnumApplications Lib "HEAccess.dll" Alias _
        "_HypEnumApplications@8" (ByVal lpfnCallBack As Long, _
        ByVal lParam As Long) As Integer


Let me know if this still doesn't make any sense.
0
 
ampapaAuthor Commented:
What does "Run-time error '453' Can't find DLL entry point EntVBGetCStrLen in Heaccess.dll" mean?
0
 
ampapaAuthor Commented:
This worked!!! WHY????

Public Function cbEnumApps(ByVal lAddr As Long, ByVal lParam As Long) As Integer

Dim lStrLen As Integer
Dim szAppName As String
Dim nRet As Integer

'Copy C string to B string
lStrLen = EntVBGetCStrLen(lAddr)
szAppName = Space(lStrLen)
nRet = EntVBCopyStr(szAppName, lAddr, lStrLen)

' add application names to logon form's combo list
If UCase(szAppName) <> "DEFAULT" Then
    'frmLogon.cmbApp.AddItem szAppName
    Debug.Print szAppName
End If

cbEnumApps = 0 'Continue enumeration

End Function
0
 
zzzzzoocCommented:
Ahh. Good. :)

>>WHY????
It's possible declaring lAddr ByRef (default) caused passing a pointer to the pointer instead of the pointer itself. Not familiar with C/C++ so I'm not sure about anything relating to it.

Feel free to post in Community Support asking to PAQ this & give you full refund. I'm up for that.
0
 
PrestaulCommented:
I think you may have been getting the overflow error because you were using explicit type casting...  i.e. When you had wLen% you were forcing it to be an integer. A % = an integer (= a short in C = 2 bytes), & = long (= 4 bytes), $ = string.  Most APIs return a long data type.  You were trying to put that value into an integer and it was causing overflow........  It is hard to say without the proper documentation, but that would explain why the original code was not working but it works now without the explicit type casting.
0
 
zzzzzoocCommented:
I was originally thinking along those lines but all of the functions used the same data-types of the variables he was passing and would've probably been casted into them anyways.
0
 
PrestaulCommented:
That's true.  It's fun trying to debug code that we can't test and can't find documentation for...  It's all speculation without something I can run and test in my own IDE.  At least it's working now!
0
 
zzzzzoocCommented:
Yep. Most of the times I overlook something simple on here because I'm not debugging it in the IDE. :D
0
 
ampapaAuthor Commented:
Thanks for all the posts and information.

Here is the function directly from the "toolkit" book except for the debug statement, it also works.

Public Function EnumAppsCallback(ByVal lAddr As Long, ByVal lParam&) As Integer
'Copy C string to B string
wLen% = EntVBGetCStrLen(lAddr&)
szapp$ = Space(wLen%)
ret% = EntVBCopyStr(szapp$, lAddr&, wLen%)
If UCase(szapp$) <> "DEFAULT" Then
'ret% = MsgBox("Application: " & szapp$)
Debug.Print szapp$
End If
EnumAppsCallback% = 0 'Continue enumeration
End Function


Here is my original:

Public Function EnumAppsCallback(laddr As Long, ByVal lParam&) As Integer
'Copy C string to B string
wLen% = EntVBGetCStrLen(laddr&)
szapp$ = Space(wLen%)
ret% = EntVBCopyStr(szapp$, laddr&, wLen%)
If UCase(szapp$) <> "DEFAULT" Or UCase(szapp$) <> "default" Then
'ret% = MsgBox("Application: " & szapp$)
Debug.Print szapp$
End If
EnumAppsCallback% = 0 'continue enumeration
End Function


The only difference I see is in the passing of the varible byval - "ByVal lAddr As Long"

I'm going to give my idea on why this worked and shoot me down if I'm wrong...

When I eliminated the "ByVal" in the varible passing I was actually using the object as opposed to using a copy of it? Similar to passing it "ByRef"? Can I drop the "type casting" or the %,$,&, etc. from the function or are they required?
0
 
zzzzzoocCommented:
>>When I eliminated the "ByVal" in the varible passing I was actually using the object as opposed to using a copy of it?
Everything is referred to by it's pointer (the starting memory address of the variable/data). So if it's ByRef, it would pass the pointer to the variable within the DLL (if that's where the callback was coming from). When it's ByVal, it'll create a copy of the variable and pass the pointer to that copy instead of the original variable. It could've crashed because the declarations didn't match, if your process couldn't access the memory the pointer referred to (you cannot directly access memory within other processes.. probably not the case for this DLL though), or if the original variable being passed was somehow modified and couldn't be used within the DLL again. This is all speculation though... as I'm not familiar with C/C++.

>>Can I drop the "type casting"
It's good practice to declare all of your variables used (Dim i as Integer, for example). If not, they'll be Variants which use a large amount of memory (and is slow when casting to another data-type). Declaring with the symbols (such as $,&) is fine but it's very "messy" looking. Place "Option Explicit" at the top of every module (Forms, Classes, Modules, etc.) and it'll force you to declare everything. A lot of errors occur because of undeclared variables and they're hard to notice!!

0
 
ampapaAuthor Commented:
So what are the meanings for the "type casing" or symbols?

0
 
zzzzzoocCommented:
They're just shortcuts to declare the variables (may be from Basic but not sure.. before I was born!).

Some examples.. $=string, %=integer, &=long, #=double, @=currency, !=single. This will have to be my last reply but maybe one more later if it's absolutely necessary. Take care. :)
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 12
  • 7
  • 6
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now