Thread: Passing an Array of Strings from VB to a C DLL

  1. #1
    Registered User
    Join Date
    Feb 2004
    Posts
    9

    Passing an Array of Strings from VB to a C DLL

    Hi everyone, I tried to avoid posting this as I realise you lot are going to destroy my already fragile confidence, but you lot are my last hope. I realise DLL's are a dirty word and I know there are probably better ways to do things but my boss is trying to get rid of me and this is the way he wants it.

    I am not sure if this should go in to a VB forum either, maybe you lot could recomend the best place for this if so.

    Here goes

    I would like to write a VB program and a DLL in C where the VB program passes an array of strings (individual strings could be any length) to the DLL. I would then like to be able to open up that array so I can manipulate individual elements and generally play with it. Finally I would like to pass an array back to the VB again so that I can open the modified array and look at the individual elements.

    The problem i am having is passing the arrays to and fro and opening the arrays both when I send them to the DLL and when it returns to the VB prog. I have done all sorts of searchs on MSDN and other places and have come up with nothing.

    I think I need a dll file, a .def file ad a vb file. I would be grateful if anyone could give me any help or if they have ever written anything like this before and have an example. I think anyone with a wee bit of knowledge could probably whip this thing up in no time at all, unfortunatley I have failed. I have tried to do this with safearrays and all sorts of stuff but VB keeps crashing.

    Any help would be truely appreciated

    Cheers

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2004
    Posts
    9
    Cheers Salem for replying I appreciate it!! Are their any major differences between the C++ code shown and the code I would write in C?

  4. #4
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    You wont have the "reinterpret_cast" and you cant declare the int inside the for loop. Other than that the ReadOutArrayOfStrings function should work in C.

  5. #5
    Registered User
    Join Date
    Feb 2004
    Posts
    9
    Sorry I must sound so thick , if i can't use the "reinterpret_cast"

    so do i use

    Code:
    SafeArrayAccessData(*StringArray, **StrPtr);
    instead of
    Code:
    SafeArrayAccessData(*StringArray, reinterpret_cast<void**>(&StrPtr));
    Thanks for all your help

  6. #6
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    Code:
    SafeArrayAccessData(*StringArray, (void**)&StrPtr);

  7. #7
    Registered User
    Join Date
    Feb 2004
    Posts
    9
    Just tried the following code and I can pass the array of strings to the C DLL from VB, thanks everyone help is truly appreciated.

    VB
    Code:
    Private Declare Sub ReadOutArrayOfStrings _
        Lib "MyC_Dll.dll" (theArray() As String)
    
    Private Sub Command1_Click()
        Dim StringArray(9) As String
        StringArray(0) = "All"
        StringArray(1) = "Work"
        StringArray(2) = "And"
        StringArray(3) = "No"
        StringArray(4) = "Play"
        StringArray(5) = "Makes"
        StringArray(6) = "Jack"
        StringArray(7) = "A"
        StringArray(8) = "Dull"
        StringArray(9) = "Boy"
        
        ReadOutArrayOfStrings StringArray
        
    End Sub
    MyC_DLL.dll
    Code:
        #include <windows.h>
    	#include <stdio.h>
    	#include <string.h>
        #include <oleauto.h>
    
    void __stdcall ReadOutArrayOfStrings(LPSAFEARRAY* StringArray)
    {
    	char** StrPtr = 0;
    	long LowerBound = 0;
    	long UpperBound = 0;
    	int i;
    
    	SafeArrayGetLBound(*StringArray,1,&LowerBound);
    	SafeArrayGetUBound(*StringArray,1,&UpperBound);
    
    	SafeArrayAccessData(*StringArray, (void**)&StrPtr);
    	for(i = LowerBound; i <= UpperBound;++i)
    		MessageBox(HWND_DESKTOP,StrPtr[i],"Hi from the DLL",MB_OK);
    	SafeArrayUnaccessData(*StringArray);
    
    }
    MyC_DLL.def
    Code:
          EXPORTS
    	ReadOutArrayOfStrings
    What I would like to do is modify the array somehow but when I try VB crashes. This is what I am trying (all code is exactly the same apart from the additional few lines in bold). Is there a reason for the VB program crashing, or am I just programming poorly ?

    MyC_DLL.dll
    Code:
         #include <windows.h>
    	#include <stdio.h>
    	#include <string.h>
        #include <oleauto.h>
    
    void __stdcall ReadOutArrayOfStrings(LPSAFEARRAY* StringArray)
    {
    	char** StrPtr = 0;
    	long LowerBound = 0;
    	long UpperBound = 0;
    	int i;
    
    	SafeArrayGetLBound(*StringArray,1,&LowerBound);
    	SafeArrayGetUBound(*StringArray,1,&UpperBound);
    
    	SafeArrayAccessData(*StringArray, (void**)&StrPtr);
    
    	for(i = LowerBound; i <= UpperBound;++i)
    		MessageBox(HWND_DESKTOP,StrPtr[i],"Hi from the DLL",MB_OK);
    	
    	for(i = LowerBound; i <= UpperBound;++i)
    		strcat(StrPtr[i],"_modified");
    		MessageBox(HWND_DESKTOP,StrPtr[i],"Hi from the DLL",MB_OK);
    
    	SafeArrayUnaccessData(*StringArray);
    }
    With this modified array is there a method for me to pass it back (or generally pass an array) to the VB program so I can manipulate or output the modified individual elements of the array.

    I thank everyone for their help in dealing with my problems it is magnificient dealing with a forum that actively cares and helps its members. I think this post should be quite useful to others in the future as well!!

    Cheers

    ADDENDUM (For completeness):

    To get this to work properly I needed to change the "Struct Member Alignment" in VC++6.0 to be "4 Bytes" because VB uses 4bytes alignment and VC++ uses 8bytes by default.

    To change go to Project>Settings
    Project Settings Dialogue appears

    CLick on the DLL in the window and select 'All Configurations', click on the "C/C++" tab, then "Code Generation" in the "Category" combo box. Under "Struct Member Alignment" change from default 8bytes to 4bytes
    Last edited by mr_nice!; 03-04-2005 at 09:11 AM.

  8. #8
    Registered User
    Join Date
    Feb 2004
    Posts
    9
    I suppose what I am trying to ask is there a way I can modify the safe array as with example code below, it crashes VB.

  9. #9
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    Stuff like this is a pain to do. Straight VB to C++ has some real nasties as the facility was introduced in VB mainly to deal with API calls. For this, strings as often converted from BSTRs to ANSI strings before VB calls the function. Sending that data back is tricky as the data used by VB is different than the data sent to the function.

    You colud try create a seperate SAFEARRAY, and pass that back seperately from the one passed in.

    I'm sure there is a way to do this the way you want, but I wouldnt bother. It's far more sensible to dump these types of call, and create a full blown COM component in C++. If you do that and stick with the VARIANT and BSTR arguments (VARIANTS can hold arrays) as well as simple data like LONG values, then you can work between C++ and VB quite easily.

    You might do well to use ATL for this as it makes it easier, and I wouldnt bother with straight C, switch to C++ as it makes COM stuff much more straightforward

  10. #10
    Registered User
    Join Date
    Feb 2004
    Posts
    9
    I have no choice, but to follow on these lines, is it not possible at all? All I require is to modify a safe array within C and then pass it back to the VB application, is it in any way possible??

    I feel I have come quite a way I have been working on this thing for a week now and had rather hoped that I was coming to the end of my problems not at the beginning at blindly bumping through another programming language that I don't really understand.

    My DLL gets data using another DLL via a call named getdat. It is my only route to that data and therefore I don't think I have too many other options

    Code:
    getdat_( f_node , &pulno , dval , tvec , &nwds , f_title , f_units , &ier , sizeof( f_node ) , sizeof( f_title ) , sizeof( f_units ) );
    I think the getdat command has something to do with FORTRAN and was probably was written before I was born.

    Infact (unfortunately) all I do know is that I am able to get data using my getdat command in a C program and my boss want to use VB to get that data.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  2. Worksafe Array of Strings
    By Hawkin in forum C Programming
    Replies: 4
    Last Post: 03-28-2008, 11:00 PM
  3. Build an array of strings dynamically
    By Nazgulled in forum C Programming
    Replies: 29
    Last Post: 04-07-2007, 09:35 PM
  4. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM
  5. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 06:58 PM