Results 1 to 38 of 38

Thread: Passing Array of Strings Between ViB and C

  1. #1

    Thread Starter
    New Member cristinuccia's Avatar
    Join Date
    Jul 2013
    Location
    Italy
    Posts
    9

    Passing Array of Strings Between ViB and C

    Hi all,

    I would be very gratefull if you could help me in solving the following problem.

    I've developed a C library which exports a function which use as input parameter an array of strings. I have to invoke this function from VB. With the help of google I've discovered the SAFEARRAY. I am able to pass the parameters from VB to C but I have no idea on how to access to the SAFEARRAY type.

    For instance, let us suppose to have the following C function:

    long __declspec (dllexport) __stdcall TryArrayString(SAFEARRAY **ppsaMyArray)
    {

    ...

    return 0;
    }


    Let us suppose that I have the following code in VB:

    Dim s(4) As String
    s(0) = "Pippo"
    s(1) = "Pluto"
    s(2) = "Paperino"
    s(3) = "Minnie"

    Dim tmp As Long

    tmp = ProvaArrayString(VarPtrStringArray(s()))


    My question is: what I have to put at place of "..." in function TryArrayString for accessing the array of strings that is contained into ppsaMyArray?

    Many thanks in advance for your help and best regards,

    Cristina

  2. #2
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by cristinuccia View Post
    My question is: what I have to put at place of "..." in function TryArrayString for accessing the array of strings that is contained into ppsaMyArray?
    The pvData member of the SAFEARRAY structure is a pointer to the first element of the array. The cElements member of the SAFEARRAYBOUND structure is the number of elements in a dimension. Each element in a VB String array is a BSTR, i.e., it is a pointer to the actual string data (much like LPWSTR).

    While that didn't answer your question directly, you probably now have a better idea of what to do with the ppsaMyArray parameter.

    Another approach that you can use is to pass the first BSTR and pass a separate parameter that specifies the number of elements in the array. In VB6, the call would look like this:

    Code:
    Private Declare Function ProvaArrayString Lib "C.dll" (ByVal pBSTR As Long, ByVal cElements As Long) As Long
    
    tmp = ProvaArrayString(VarPtr(s(0&)), 4&)

    You may also want to refer to How To Get the Address of Variables in Visual Basic.
    Last edited by Bonnie West; Jul 28th, 2013 at 07:32 PM.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  3. #3
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Assume this as your VB6 declaration:-
    vb Code:
    1. Private Declare Sub ReadVB6StringArray Lib "PInvokeTestingGround.dll" (strn() As String)

    And this as its usage:-
    vb Code:
    1. '
    2.     Dim s(4) As String
    3.    
    4.     s(0) = "Pippo"
    5.     s(1) = "Pluto"
    6.     s(2) = "Paperino"
    7.     s(3) = "Minnie"
    8.  
    9.     ReadVB6StringArray s

    This is what you C++ function should look like:-
    c++ Code:
    1. //
    2. void _stdcall ReadVB6StringArray(SAFEARRAY **strings)
    3. {
    4.    
    5.     SAFEARRAY* vbarray =(*strings);
    6.  
    7.     ULONG numElements = vbarray->rgsabound[0].cElements;
    8.     int lbound = vbarray->rgsabound[0].lLbound;
    9.  
    10.     BSTR* vbStrings=(BSTR*) vbarray->pvData;
    11.  
    12.     // Loops through the strings
    13.     for(int i=lbound; (i < lbound+numElements);i++)
    14.     {
    15.         //Gets the current string
    16.         BSTR current = vbStrings[i];
    17.        
    18.     }
    19.    
    20.  
    21. }

    Now, I'm not 100% sure that C++ function works since its really a royal pain in my ass to find a way to convert VB's BSTR string into a C string to test reading the strings. But I'm reasonably certain its reading the SAFEARRAY correctly. I'll leave finding a way to convert from a BSTR up to you.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  4. #4
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    Now, I'm not 100% sure that C++ function works since its really a royal pain in my ass to find a way to convert VB's BSTR string into a C string to test reading the strings. ... I'll leave finding a way to convert from a BSTR up to you.
    It's my understanding that the BSTR data type is compatible with the LPWSTR/LPCWSTR data type. Am I wrong?
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  5. #5
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Bonnie West View Post
    It's my understanding that the BSTR data type is compatible with the LPWSTR/LPCWSTR data type. Am I wrong?
    Well, partially. Functions that take an LPWSTR are supposed to be able to handle a BSTR but BSTR functions aren't supposed to be compatible with LPWSTR. Now in practice its not so clear cut. These string typedefs are such a tangled mess that unless you've been deal with them constantly, its basically a hit-and-miss type thing. I'm sure I have a function somewhere that can convert BSTRs to C strings as I've done this type of thing before but its among hundreds of projects that have gathered on my HD for like a decade now. Finding it alone is full time job.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  6. #6
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    Assume this as your VB6 declaration:-
    vb Code:
    1. Private Declare Sub ReadVB6StringArray Lib "PInvokeTestingGround.dll" (strn() As String)

    But I'm reasonably certain its reading the SAFEARRAY correctly.
    I've just realized something. I almost forgot that VB6 implicitly converts from Unicode to ANSI to Unicode again any string, even an arrray of strings, when you pass it to an external function As String. The KB article I linked above discusses this issue. In order to circumvent that, the article recommended calling a tweaked declaration of the native VarPtr function in a type library. It appears that the OP is already using that custom declare:

    Code:
    tmp = ProvaArrayString(VarPtrStringArray(s()))
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  7. #7
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Bonnie West View Post
    I've just realized something. I almost forgot that VB6 implicitly converts from Unicode to ANSI to Unicode again any string, even an arrray of strings, when you pass it to an external function As String.
    Good work Bonnie! You're right. I forgot about that completely as well. I fixed the C++ function to account for that and it works now:-
    c++ Code:
    1. //
    2. void _stdcall ReadVB6StringArray(SAFEARRAY **strings)
    3. {
    4.    
    5.     SAFEARRAY* vbarray =(*strings);
    6.  
    7.     ULONG numElements = vbarray->rgsabound[0].cElements;
    8.     LONG lbound = vbarray->rgsabound[0].lLbound;
    9.  
    10.     char** vbStrings=(char**) vbarray->pvData;
    11.  
    12.     // Loops through the strings
    13.     for(int i=lbound; (i < lbound+numElements);i++)
    14.     {
    15.         //Gets the current string
    16.         char* current = vbStrings[i];
    17.        
    18.         MessageBoxA(HWND_DESKTOP,current,"Current String" ,MB_OK);
    19.  
    20.     }
    21.    
    22.  
    23. }
    Last edited by Niya; Jul 29th, 2013 at 04:15 AM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  8. #8

    Thread Starter
    New Member cristinuccia's Avatar
    Join Date
    Jul 2013
    Location
    Italy
    Posts
    9

    Re: Passing Array of Strings Between ViB and C

    Many thanks guys for your quick reply!

    I will try and I keep you posted.

    Thanks again,

    Cri

  9. #9
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Note that the last version of the C++ function I posted is meant to work on arrays passed in the normal way. If you use VarPtr to pass it, you'd be back to the problem of converting it to a C style string.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  10. #10

    Thread Starter
    New Member cristinuccia's Avatar
    Join Date
    Jul 2013
    Location
    Italy
    Posts
    9

    Re: Passing Array of Strings Between ViB and C

    Many thanks Niya and Bonnie. It works!

    I would like to take advantage of your courtesy for another small question. Now suppose that the C function wants to return an array of string. For instance:

    Code:
    void _stdcall Foo(char **s)
    {
       s[0] = strdup("pippo");
       s[1] = strdup("pluto");
       s[2] = strdup("paperino");
    }
    and I want to invoke that function from VB:

    Code:
    Dim s(3) As String
    Foo s
    Of course the above code is just for explaining what I like to do but, obviously, it does not work. Could you help me again?

    Thanks a lot in advance,

    Cri

  11. #11
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Its easy, just change the string. It will be marshalled back to VB properly:-
    c++ Code:
    1. //
    2. void _stdcall ReadVB6StringArray(SAFEARRAY **strings)
    3. {
    4.    
    5.     SAFEARRAY* vbarray =(*strings);
    6.  
    7.     ULONG numElements = vbarray->rgsabound[0].cElements;
    8.     LONG lbound = vbarray->rgsabound[0].lLbound;
    9.  
    10.     char** vbStrings=(char**) vbarray->pvData;
    11.  
    12.     // Loops through the strings
    13.     for(int i=lbound; (i < lbound+numElements);i++)
    14.     {
    15.         //Gets the current string
    16.         char* current = vbStrings[i];
    17.        
    18.         //Changes the strings in the array to
    19.         //uppercase. The changes will be reflected
    20.         //back in VB
    21.         if (current != NULL){
    22.             strupr(current);}
    23.  
    24.        
    25.  
    26.     }
    27.    
    28.  
    29. }
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  12. #12
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Passing Array of Strings Between ViB and C

    I'm not sure if there's a SafeArray function that you can call in order to manipulate the array variable passed by VB, but you may want your function to work in a similar way with the CommandLineToArgvW API function.


    EDIT

    Sorry Niya, I didn't see your post...
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  13. #13

    Thread Starter
    New Member cristinuccia's Avatar
    Join Date
    Jul 2013
    Location
    Italy
    Posts
    9

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    Its easy, just change the string. It will be marshalled back to VB properly:-
    c++ Code:
    1. //
    2. ...
    3.         //Changes the strings in the array to
    4.         //uppercase. The changes will be reflected
    5.         //back in VB
    6.         if (current != NULL){
    7.             strupr(current);}
    8. ...
    9. }
    Thanks Niya for your quick reply. The problem with your code is that you are manipulating stings already allocated in memory. In your example you are using strupr that does not allocate new memory as the length of the string remains unchanged. But now suppose that you want to modify the generic element of the array with a new string which requires memory allocation (like in my example). Or, suppose something like as follows:
    c++ Code:
    1. strcpy(current, "hello world!");
    Now, if current is a string of, for instance, 5 characters, if a copy a string longer than 5 characters I think that I will get a memory protection error. What do you think?

    Thanks,

    Cri

  14. #14
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Before I answer this, I need you to tell me if you have any thoughts towards changing the array itself. Perhaps by removing or adding elements. That needs consideration as it may affect the approach that needs to be taken.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  15. #15

    Thread Starter
    New Member cristinuccia's Avatar
    Join Date
    Jul 2013
    Location
    Italy
    Posts
    9

    Re: Passing Array of Strings Between ViB and C

    Actually, I want to develop a function in which one of its output parameters is an array of strings. Based on this I thought to pass it an array of empty strings and make the function fill up these strings. So, the number of elements of the input array does not change (I do not need to insert or remove elements of the array). The only thing I want to do is modifying the strings in the vector. Please note that with the term modify I mean that a string can even increase in size.

  16. #16
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by cristinuccia View Post
    The only thing I want to do is modifying the strings in the vector.
    You'll most likely need to call one or more of the BSTR functions.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  17. #17
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by cristinuccia View Post
    Actually, I want to develop a function in which one of its output parameters is an array of strings. Based on this I thought to pass it an array of empty strings and make the function fill up these strings.
    As long as you work with the dedicated functions from the SafeArray-API and the BSTR-API (mostly defined in oleauto.h),
    you can stay conform to the VB-end, since the above functions are at play also "on the other side".

    The only problem as I see it - is (for a C-programmer) to understand (or avoid) those weird automatic and implicit BSTR-ANSI-BSTR conversions on the VB-end
    (which take place as soon as one is passing something that has BSTRs in it, to a Declared Dll-function-call.)

    To avoid those conversions (and mostly these days one has #define UNICODE enabled also at the C-end) one should pass only Int-Typed Pointers to the Dll-functions - and thus hide (from VB) that those Params point to "something with Strings in it".

    So, well - here's my take at an Unicode-capable exchange with a C-Dll-Source (which internally has to be switched to #define UNICODE)

    The C-side with two functions (one which is just a "passive reader" - but the other function accepts even uninitialized SafeArrays, does allocations and returns a properly filled SafeArray of BSTRs back to VB):

    Code:
    DLL_EXPORT void __stdcall ReadBStrSafeArray(SAFEARRAY** ppsa)
    {
    	if (!ppsa) return;
    	
    	SAFEARRAY* psa = *ppsa; //deref, because from VB we got the pointer to the Variable which *hosts* the SafeArray, not the SafeArray itself
    	if (!psa) return;
    	
    	BSTR* bstrArr;
    	HRESULT hr;
    
    	hr = SafeArrayAccessData(psa, (void **) &bstrArr); //map the pvData-pointer and lock the SafeArray
    	
    	if (hr == S_OK) {
    		for(long i=0; (i < psa->rgsabound[0].cElements); i++) {
    			MessageBox (0, bstrArr[i], L"Unicode-capable BSTRArr-Enumeration from within C-DLL", MB_ICONINFORMATION);
    		}
    	}
    	hr = SafeArrayUnaccessData(psa); //release the locking of the SafeArray after our loop is finished
    }
    
    
    DLL_EXPORT void __stdcall InitAndFillBStrSafeArray(SAFEARRAY** ppsa)
    {
    	if (!ppsa) return;
    	
    	SAFEARRAY* psa = *ppsa; //deref again
    	if (psa) SafeArrayDestroy(psa); //cleanup (and automatically free the current Arr-Members, if there are any) 
    
    	psa = SafeArrayCreateVector(VT_BSTR, 0, 3);
    	*ppsa = psa; //ensure, that our new target-array is returned "ByRef" in the passed VarPtr
    	if (!psa) return;
     
    	BSTR* bstrArr;
    	HRESULT hr;
     
    	hr = SafeArrayAccessData(psa, (void **) &bstrArr); //map the pvData-pointer and lock the SafeArray
    	
    	if (hr == S_OK) {
    		BSTR btmpLeft, btmpRight;
    		for(long i=0; (i < psa->rgsabound[0].cElements); i++) {
    			btmpLeft = SysAllocString(L"C-entered WideChar-Item at "); //just to demonstrate a BSTR-concatenation at this occasion
    			hr = VarBstrFromI4(i, 0, 0, &btmpRight); //the left part was created above - here comes the right part ("casted" from an Int32)
    		   
    			if (hr == S_OK) VarBstrCat(btmpLeft, btmpRight, &bstrArr[i]); //store the concat-result in our so far empty &bstrArr[i]-slot
     
    			SysFreeString(btmpLeft); //VarBstrCat doesn't free the left and right BSTR-Vars...
    			SysFreeString(btmpRight); //so we do it by hand here
    		}
    	}
    	hr = SafeArrayUnaccessData(psa); //release the locking of the SafeArray after our loop is finished
    }
    And here's the VB-side, which shows a method - how to retrieve the VarPtr of a SafeArray whilst avoiding any ANSI-conversions.

    Code:
    'Into a Form, then click the Form
    Option Explicit
    
    Private Declare Sub MemCopy Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal CB&)
    
    Private Declare Sub ReadBStrSafeArray Lib "d:\test.dll" (ByVal pSafeArrVar As Long)
    Private Declare Sub InitAndFillBStrSafeArray Lib "d:\test.dll" (ByVal pSafeArrVar As Long)
    
    Private Sub Form_Click()
    Dim i As Long
    
      'first we feed something into the C-Dll (MessageBoxes are raised from within the C-Dll-Routine)
      ReDim SArrIn(0 To 2) As String
      For i = 0 To UBound(SArrIn)
        SArrIn(i) = "VB-entered WideChar-Item at " & i
      Next
      ReadBStrSafeArray GetSafeArrVarPtr(SArrIn)
      
      'now we retrieve a BSTR-SafeArray from the C-Dll without the need to initialize it on the VB-end
      Dim SArrOut() As String
      InitAndFillBStrSafeArray GetSafeArrVarPtr(SArrOut)
      For i = 0 To UBound(SArrOut)
        MsgBox SArrOut(i)
      Next
    End Sub
      
    Private Function GetSafeArrVarPtr(Arr) As Long 'a method, which works without any implicit ANSI-conversions on String-arrays
      If IsArray(Arr) Then MemCopy GetSafeArrVarPtr, ByVal VarPtr(Arr) + 8, 4
    End Function
    HTH

    Olaf

  18. #18
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Schmidt View Post
    The only problem as I see it - is (for a C-programmer) to understand (or avoid) those weird automatic and implicit BSTR-ANSI-BSTR conversions on the VB-end
    Why would you want to avoid that ? It makes things on the VB side more verbose. IMO, its more elegant to have these functions work like your typical VB function. Your method is actually how you would write more suitable to export through a COM type library.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  19. #19
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    Why would you want to avoid that ?
    Because unnecessary conversions are exactly that - unnecessary.

    Your point has value, when on the C-end there's absolutely no desire to work already unicode-aware (per #define UNICODE mode).

    But if there is - then avoiding the conversions on the VB-end is mandatory IMO
    (no need to waste CPU-cycles or to risk information-loss whilst an already existing Wide-String (on the VB-end) gets mangled through the current-locale-mapper back and forth).

    And even when you "force ANSI-conversion-mode" on the VB-side - e.g. when declaring:

    Private Declare Sub InitAndFillBStrSafeArrayANSI Lib "test.dll" (SafeArrayVar() As String) '<- and BTW, SafeArrayVar() As Any would not help to avoid ANSI-conv.

    You will still have to deal (at the C-end) with a whole lot of "Ole-stuff and functions" to get things right (for the heavily COM and OLE-based "VB-client") -
    so since those functions will be used anyways already per oleauto.h, then why not go "all the way" and do it "properly in W-Mode throughout".

    My example was just trying to encourage the OP to do just that.

    And in case one wants to avoid the "verboseness" as you put it (on the VB-side), a simple TypeLib-Definition of the exported API-Call in question would be enough -
    then the BSTR-Safearrays in question could be passed directly (in the same way as to any other VB-Project-internal Function which receive SafeArrays in their Param-Args).

    Olaf

  20. #20

    Thread Starter
    New Member cristinuccia's Avatar
    Join Date
    Jul 2013
    Location
    Italy
    Posts
    9

    Re: Passing Array of Strings Between ViB and C

    Dear Schmidt,

    Many many thanks for your help. I've tried your code and it works! Thanks a lot!

    Of course, I have adapted it for my purposes and I've still a small problem. In your sample code you use function SysAllocString to allocate a constant string. For instance, using your notation we can do:

    Code:
    bstrArr[i] = SysAllocString(L"hello world!");
    Now, suppose that I have not a constant string but something like the following:

    Code:
    string mystr = "hello world!";
    bstrArr[i] = SysAllocString(mystr.c_strt());
    Unfortunately, the above code does not work and I do not understand why. casting to (const unsigned short *) it compiles but it does not assign the correct string. Could you help me to solve this last issue?

    Thanks a lot in advance and best regards,

    Cristina

  21. #21
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by cristinuccia View Post
    Code:
    string mystr = "hello world!";
    bstrArr[i] = SysAllocString(mystr.c_strt());
    Unfortunately, the above code does not work and I do not understand why. casting to (const unsigned short *) it compiles but it does not assign the correct string. Could you help me to solve this last issue?
    The above doesn't work, because you need to perform an ANSI-to-BSTR-conversion at the C++ end of things,
    which you could avoid when you'd use:
    std::wstring mystr = L"hello world!";
    instead of your:
    std::string mystr = "hello world!";
    from above...

    Meaning that you work unicode- (or at least WString) aware throughout (also at the C/C++ side).

    If you want to keep up "doing ANSI" at the C++ Dlls end, then you need to introduce
    ANSI2BSTR-conversion-routines ...
    (in case of C++ you could use _bstr_t for shorter notation -
    ...maybe interesting to look at this article here: http://msdn.microsoft.com/en-us/libr...8VS.80%29.aspx
    ...or just google for [ANSI to BSTR C++]

    The small helper-function below is C-compatible, not using any of the C++ stuff shown in the above link,
    but should work when you use it this way: bstrArr[i] = Ansi2Bstr(mystr.c_strt());

    Code:
    BSTR Ansi2Bstr(LPCSTR lpSrc){
        if (!lpSrc) return 0;
    	
        int  LenSrc = strlen(lpSrc);
        BSTR lpDst = SysAllocStringLen(NULL, LenSrc);
     
        if (!lpDst) return 0;
    	
        MultiByteToWideChar(CP_ACP, 0, lpSrc, LenSrc, lpDst, LenSrc);
        return lpDst;
    }
    Just out of interest - is the C/C++ Dll only a small helper to speed some things up on the VB-side?
    (in this case there'd be a lot of things one can do with regards to fast string-processing directly in VB6,
    which will perhaps beat what you currently have in VC++)

    Or is the VB-Dll-interface only a small window into a "long existing, very broad and very complex C++ lib, which is used also in other contexts by other languages"?

    What does your C++ Dll do currently (if you are allowed to tell us that much).

    Olaf

  22. #22
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Schmidt View Post
    (in this case there'd be a lot of things one can do with regards to fast string-processing directly in VB6,
    which will perhaps beat what you currently have in VC++)
    Generally speaking there's not a chance in hell. In her case though you may be right since she is still dealing with BSTRs on the C++ side but you can write string processing functions in C++ that is faster by great magnitudes than even the best VB6 equivalent. I once wrote a parser in VB6 which I needed to parse large texts on every keystroke in order to facilitate a VB-like IDE. When I loaded a file of a size like a 100 KBs or so, the IDE would slow down tremendously. I mean like every keystroke would cause something like a 6 second delay. I re-wrote the parser in C++ and exported it through functions and it could now process texts well up to 500 KBs in milliseconds. The problem with string processing in VB6 is immutability. This limits efficiency.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  23. #23
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    Generally speaking there's not a chance in hell. ... but you can write string processing functions in C++ that is faster by great magnitudes than even the best VB6 equivalent.
    I believe it was Matt Curland who pioneered the technique of using a SafeArray hack to process BSTRs as Integer arrays. The following excerpt was taken from his book Advanced Visual Basic 6:

    Quote Originally Posted by Matthew Curland
    Strings as Numbers

    A string is a set of individual characters in which every character is actually a number. As a general programming principle, you should treat strings as arrays of numbers rather than as autonomous units to get optimal performance from string routines. Unfortunately, VB offers no built-in mechanism for treating a String as a simple array of Integer numbers. This forces VB programmers to use string allocations for operations that could be numeric. This section looks at treating a VB String as an array of Integer values, allowing you to apply string algorithms that operate on numbers instead of normal string variables. I will rely heavily on the SafeArray techniques discussed in Chapter 2 and the ArrayOwner lightweight techniques from Chapter 8.
    You might be interested in checking out this class module which makes that technique very easy to apply.

    Quote Originally Posted by Niya View Post
    The problem with string processing in VB6 is immutability. This limits efficiency.
    Even without using advanced techniques, VB6 already has the Mid$ statement which can modify any BSTR in place.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  24. #24
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    That is a very interesting approach Bonnie. The only question is, just how much extra performance can one squeeze from this approach compared to its C++ equivalent.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  25. #25
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    The only question is, just how much extra performance can one squeeze from this approach compared to its C++ equivalent.
    I have not done any benchmarks, but I have reason to believe that a highly optimized VB6 code that uses such a technique can, at least, compete well with its C++ equivalent. I once tried making my own simple hex viewer (still unfinished) using just the MidB$ and Select Case statements. I initially thought it was very slow, especially when I tried opening files greater than 1 MB in size. Then I learned about the CryptBinaryToString API function, which can do the same and more. Imagine my surprise when I found out that the API was even slower than the code generated by VB6! So, contrary to common perception, VB6 isn't all that slow. You just have to know how to make it run fast. BTW, I've seen VB6 codes that process Strings using injected ASM code. I'm aware that C++ can also do the same.

    I don't know about Schmidt, but I'm interested in comparing the String processing speed of both C++ and VB6 (and also of VB.Net/C#).
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  26. #26
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Well the VB6 compiler can compile to native code so in theory it can be as fast as C++. I too would like to tackle doing comparisons between the languages. We'd need to come up with some kind of string processing operation that's simple enough to write in a short time yet rigorous enough to provide an accurate assessment. Or maybe a few different yet simple operations after which we can aggregate the results of each implementation in both languages.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  27. #27
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    Well the VB6 compiler can compile to native code so in theory it can be as fast as C++. I too would like to tackle doing comparisons between the languages. We'd need to come up with some kind of string processing operation that's simple enough to write in a short time yet rigorous enough to provide an accurate assessment. Or maybe a few different yet simple operations after which we can aggregate the results of each implementation in both languages.
    There's no need to "come up with some simple StringOp" anymore to prove that you are wrong with your statement about speed.
    E.g. the vb6-runtime is written in C++ and comes with a Replace-function, which in tests proved up to 10-15 times slower than an optimized Replace written in VB6 itself.

    http://www.xbeat.net/vbspeed/c_Replace.htm#Replace10

    In the german newsgroups we dealt with safearrays already before Matt Curlands book came out - not sure about the english VB-
    newsgroups at that time - I was not yet participating there because I couldn't speak more than a few words of the english language then.

    Bonnie thankfully corrected your wrong statement about immutability of BSTRs already on two counts (SafeArrays and the Mid-statement),
    so not much to say anymore for the moment - but if I may suggest something...;
    you shouldn't shoot as fast as you're currently doing (also in other threads) ... That you failed writing a fast parser in
    VB6 doesn't mean that it cannot be done Niya - don't judge from your own capabilities on the capabilities of others -
    especially not about what can be done in a given language - especially when it is one, you had not much practice with
    over the last years.


    Olaf

  28. #28
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Schmidt View Post
    There's no need to "come up with some simple StringOp" anymore to prove that you are wrong with your statement about speed.
    E.g. the vb6-runtime is written in C++ and comes with a Replace-function, which in tests proved up to 10-15 times slower than an optimized Replace written in VB6 itself.

    http://www.xbeat.net/vbspeed/c_Replace.htm#Replace10

    In the german newsgroups we dealt with safearrays already before Matt Curlands book came out - not sure about the english VB-
    newsgroups at that time - I was not yet participating there because I couldn't speak more than a few words of the english language then.

    Bonnie thankfully corrected your wrong statement about immutability of BSTRs already on two counts (SafeArrays and the Mid-statement)
    Fair enough, I'll concede this point to you. However:-
    Quote Originally Posted by Schmidt View Post
    That you failed writing a fast parser in
    VB6 doesn't mean that it cannot be done Niya - don't judge from your own capabilities on the capabilities of others -
    I will not waste my time trying to hack VB6 in an effort to fit a square peg in a round hole. Its far easier to simply write the damn thing in C++. String processing isn't the only thing VB6 suffers at(barring the mentioned techniques). I also had experience with its terrible performance with image processing. I remember writing a screen saver and I wanted pretty effects but was unwilling to learn DirectX as I didn't really want all the bells and whistles of it. I just needed a couple of functions to do some simple blending effects and some colour matching if I remembered correctly. My initial attempts in VB6 yielded disastrous performance. I ended up porting most of the image processing to a C++ library and saw significant improvement in performance.

    VB6 has way too much overhead for these types of algorithms to work efficiently without hacking. If you can hack your way around it, then more power to you. But if you are capable of writing them in C/C++ then I'd strongly recommend it as the better approach. I endorse the OP's attempt to do this in C++ if her reason is for performance.
    Last edited by Niya; Aug 18th, 2013 at 05:35 AM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  29. #29
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Oh and I didn't even mention the fact the Visual C++ compiler understands embedded assembly. Could you hack the high level of performance assembly code algorithms can produce out of VB6 ?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  30. #30
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    I will not waste my time trying to hack VB6 in an effort to fit a square peg in a round hole. Its far easier to simply write the damn thing in C++.
    Nope, VB6-code for fast String-processing (when dealing at the char-value-level) is not much different from C++-routines (and Char-Array-usage there).

    Quote Originally Posted by Niya View Post
    String processing isn't the only thing VB6 suffers at(barring the mentioned techniques).
    VB6 does *not* suffer at String-processing, even when you take the SafeArray-approach away - since it is dead-easy to e.g.
    start (for example when working on files) already with Char-Arrays in the first place - and then there's always the possibility to cast
    a BSTR-copy into a ByteArray directly. And for many (most) scenarios VBs Instr-function or Split/Join and the Mid-statement are already fast enough.

    Quote Originally Posted by Niya View Post
    I also had experience with its terrible performance with image processing.
    As with your statement about string-processing-speed above - to image-processing I will say the same -
    VB6-native-compiler output works at the level of the VC++ compiler version 6.
    And thus, if you experienced "terrible performance with image processing", then it was definitely your fault, not the fault of the VB6-language or -compiler.

    Quote Originally Posted by Niya View Post
    I just needed a couple of functions to do some simple blending effects and some colour matching if I remembered correctly.
    My initial attempts in VB6 yielded disastrous performance.
    I ended up porting most of the image processing to a C++ library and saw significant improvement in performance.
    Post your C++ lib with some of your "blending or color-matching ops" - and I'm sure we can show you, how it's done properly in VB6.

    Quote Originally Posted by Niya View Post
    VB6 has way too much overhead for these types of algorithms to work efficiently without hacking.
    A blurry statement that, sorry to say... not sure what exactly is so difficult to understand in, that VB6 can compile roughly to the same speed-level as VC++6.

    Quote Originally Posted by Niya View Post
    If you can hack your way around it, then more power to you.
    Not sure what you mean with "hacking" - is it the usage of pointers in VB (you know, the same things you do when writing C++ code)?
    Seems you are of the opinion, that when you work with pointers in C++, then it's "a nice, clean and fast way" - but when you use basically
    the same Pointer-approach in VB6 per VartPtr/StrPtr & Co, then it is suddenly an "evil hack".

    Quote Originally Posted by Niya View Post
    But if you are capable of writing them in C/C++ then I'd strongly recommend it as the better approach. I endorse the OP's approach as the better approach if she's indeed seeking performance by using C++.
    Writing fast routines requires first and foremost *experience*, no matter what language (especially then, when the languages in question are pretty close since they compile already "natively").
    It is the developer who decides (in the end) how fast an algorithms implementation is capable to work. I mean, you should have been able to come up with that on your own,
    just from the example I've posted ...
    I'm not sure if Cristina is able to work already at the level of the experienced MS-developers which implemented the original C++ based Replace-function in the VB6-runtime -
    If she has more experience with VB6, then there's a very good chance, that she's able to write something faster directly in VB6 (with some guidance here in the Forum).


    Olaf
    Last edited by Schmidt; Aug 18th, 2013 at 07:39 AM.

  31. #31

    Thread Starter
    New Member cristinuccia's Avatar
    Join Date
    Jul 2013
    Location
    Italy
    Posts
    9

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Schmidt View Post
    ...
    Just out of interest - is the C/C++ Dll only a small helper to speed some things up on the VB-side?
    (in this case there'd be a lot of things one can do with regards to fast string-processing directly in VB6,
    which will perhaps beat what you currently have in VC++)

    Or is the VB-Dll-interface only a small window into a "long existing, very broad and very complex C++ lib, which is used also in other contexts by other languages"?

    What does your C++ Dll do currently (if you are allowed to tell us that much).

    Olaf
    Many thanks Olaf as usual for your reply. No, I have not any constraint on performance, so I looked for a working solution even if slow.

    Thanks a lot again, :-)

    Cri

  32. #32
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Schmidt View Post
    Not sure what you mean with "hacking" - is it the usage of pointers in VB (you know, the same things you do when writing C++ code)?
    Among other things, yes.

    Quote Originally Posted by Schmidt View Post
    Seems you are of the opinion, that when you work with pointers in C++, then it's "a nice, clean and fast way" - but when you use basically
    the same Pointer-approach in VB6 per VartPtr/StrPtr & Co, then it is suddenly an "evil hack".
    It is an evil hack.

    Note that VarPtr is a function. I'd expect like all functions a stack frame needs to be prepared every time its called. Surely setting up a stack frame consumes extra cycles. Do you think you would get such overhead using pointers in C++ ? Do you believe that the C++ compiler would produce calls into a whole function just to access a bit of memory ?

    Surely if VB6 was meant to be decent with pointers, MS would have provided a more efficient means of dealing with them. But they didn't hence techniques that involve VarPtr are hacks. You're basically "hacking" the language to do something it was not really meant to do.

    Quote Originally Posted by Schmidt View Post
    A blurry statement that, sorry to say... not sure what exactly is so difficult to understand in, that VB6 can compile roughly to the same speed-level as VC++6.
    VB6 can compile to native code yes but VB6 is natively COM. What do you think it compiles to when you say...access an array ? Its most likely going to compile calls into OLE functions like SafeArrayAccessData(Feel free to correct me if I'm wrong ) If I need to process an array of pixels every 50 milliseconds, this overhead is totally unacceptable. I need a compiler gives me direct access to the memory without the overhead of calling into functions like SafeArrayAccessData. C++ gives you pointers which work very well with arrays and the C++ compiler no doubt uses far fewer native instructions for array operations than you would get from the VB6 compiler.

    Quote Originally Posted by Schmidt View Post
    Writing fast routines requires first and foremost *experience*, no matter what language (especially not, when the languages in question are pretty close since they compile already "natively").
    Don't kid yourself, the VC++ compiler doesn't compile code close to what the VB6 compiler would do.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  33. #33
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by cristinuccia View Post
    No, I have not any constraint on performance, so I looked for a working solution even if slow.
    Well that settles the matter. She could do it pure in VB6 then, if that's more desirable.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  34. #34
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    It is an evil hack.
    No, using Pointers is not an evil hack - if it is - then using C/C++ is "evil hacking throughout".

    Quote Originally Posted by Niya View Post
    Note that VarPtr is a function. I'd expect like all functions a stack frame needs to be prepared every time its called. Surely setting up a stack frame consumes extra cycles. Do you think you would get such overhead using pointers in C++ ? Do you believe that the C++ compiler would produce calls into a whole function just to access a bit of memory ?
    No, to "access a bit of memory" in a very fast way, one usually uses variables ... as e.g. in:
    pSomething = VarPtr(Something) '<-- *before* entering a tight loop

    Quote Originally Posted by Niya View Post
    Surely if VB6 was meant to be decent with pointers, MS would have provided a more efficient means of dealing with them. But they didn't hence techniques that involve VarPtr are hacks. You're basically "hacking" the language to do something it was not really meant to do.
    No, that's incorrect information...

    Quote Originally Posted by Niya View Post
    VB6 can compile to native code yes but VB6 is natively COM. What do you think it compiles to when you say...access an array ? Its most likely going to compile calls into OLE functions like SafeArrayAccessData(Feel free to correct me if I'm wrong ) If I need to process an array of pixels every 50 milliseconds, this overhead is totally unacceptable.
    No, that's incorrect information...

    Quote Originally Posted by Niya View Post
    I need a compiler gives me direct access to the memory without the overhead of calling into functions like SafeArrayAccessData. C++ gives you pointers which work very well with arrays and the C++ compiler no doubt uses far fewer native instructions for array operations than you would get from the VB6 compiler.
    ...
    Don't kid yourself, the VC++ compiler doesn't compile code close to what the VB6 compiler would do.
    If that really would be the case, then it should not be possible at all, to beat e.g. the native VB6-Replace-function performance-wise.

    So, no - the above is incorrect information too.

    Please open a new thread, if you want me to educate you further about this topic.

    And with regards to Cristinas: "No, I have not any constraint on performance, so I looked for a working solution even if slow."

    I think you misunderstood her ... what she perhaps meant was, that it doesn't really matter to her,
    if a pure VB6-solution would be faster - since the current status-quo suits here just fine...

    As said, just open a new thread, when you want more info - I think that this thread here can be considered closed
    (at least I'm done with it now).


    Olaf

  35. #35
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Oh God....you are really dense. Look at this:-
    vb Code:
    1. '
    2. Private Sub Test()
    3.     'Lets just pretend this array has
    4.     'data
    5.     Dim numbers() As Integer
    6.    
    7.     For i = LBound(numbers) To UBound(numbers)
    8.         numbers(i) = numbers(i) * 2
    9.     Next
    10.  
    11. End Sub

    Are you really going to pretend that the VB compiler would produce native code that would execute as fast as this compiled by a C++ compiler:-
    c++ Code:
    1. //
    2. void Test()
    3. {
    4.  
    5.     // Lets pretend this pointer
    6.     // points to a list of integers
    7.     int* numbers;
    8.  
    9.     int numElements=1000;
    10.  
    11.     for(int i=0;i<numElements;i++)
    12.     {
    13.         numbers[i]=numbers[i]*2;
    14.     }
    15.  
    16.  
    17.  
    18. }

    The VB6 array is a SafeArray. It has to be accessed through COM API calls. The C++ uses simple pointer arithmetic. It should be obvious which one would execute faster. Are you seriously suggesting that this is not true ?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  36. #36
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Passing Array of Strings Between ViB and C

    Quote Originally Posted by Niya View Post
    Oh God....you are really dense.
    Don't resort to rudeness Niya.

    Quote Originally Posted by Niya View Post
    The VB6 array is a SafeArray. It has to be accessed through COM API calls.
    The C++ uses simple pointer arithmetic. It should be obvious which one would execute faster.
    Are you seriously suggesting that this is not true ?
    As already said, please open a new thread for that - and maybe enhance your C++-loop above to perform something
    useful, as e.g. a Gaussian-Blur or an Alpha-Blending-Loop on larger (e.g. 1280x1024) Bitmaps for example
    (or do a MandelBrot-calculation on a given Bitmapsize with a given depth or whatever).

    Just come up with something useful to expose the allegedly "huge disadvantages" of VB-safearrays in a bit of
    context, compile it into a (StdCall-exporting) Dll - and then compare if the VB-solution really is "slower by magnitudes".


    Olaf

  37. #37
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Passing Array of Strings Between ViB and C

    Well if VB6 cannot compete with C++ for something simple, what makes you think it could possibly compete with something more complicated like alpha blending ?

    I just did a simple test and here is the result:-
    Code:
    VB Time:3925.62500000349
    C++ Time:424.406250000175
    The time is measured in milliseconds.

    Here is the VB6 code:-
    vb Code:
    1. '
    2. Private Sub DoTestVB()
    3.     Dim numElements As Long
    4.     Dim numbers() As Long
    5.    
    6.     Dim x As Long
    7.        
    8.     numElements = 10000
    9.    
    10.     ReDim numbers(1 To numElements)
    11.        
    12.     For x = 1 To numElements
    13.    
    14.         For i = 1 To numElements
    15.             numbers(i) = i * 100
    16.         Next
    17.  
    18.     Next
    19.    
    20.  
    21. End Sub

    Here is the C++ code:-
    c++ Code:
    1. //
    2. void _stdcall DoTestC()
    3. {
    4.     int numElements = 10000;
    5.     int* numbers;
    6.  
    7.     numbers=new int[numElements];
    8.  
    9.     for(int x=0;x<numElements;x++)
    10.     {
    11.         for(int i=0;i<numElements;i++)
    12.         {
    13.             numbers[i]=i*100;
    14.         }
    15.        
    16.     }
    17.  
    18.     delete numbers;
    19. }

    Here is the timing code, written on the VB6 side:-
    vb Code:
    1. '
    2.     Dim T As Double
    3.    
    4.     T = Timer
    5.     DoTestVB
    6.  
    7.     Debug.Print "VB Time:" + CStr((Timer - T) * 1000)
    8.    
    9.     T = Timer
    10.     DoTestC
    11.     Debug.Print "C++ Time:" + CStr((Timer - T) * 1000)

    Such a simple operation yet look at how lopsided the performance results were. The C++ version is 10 times faster. Why is this even an argument. Its clear which language is better to write that alpha blending routine in or that Gaussian-Blur.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  38. #38
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Passing Array of Strings Between ViB and C

    Since you seem unwilling to create a new thread for that, I've now done so myself: http://www.vbforums.com/showthread.p...ative-compiler

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width