Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C#
  4. Array of strings to old DLL?

Array of strings to old DLL?

Scheduled Pinned Locked Moved C#
csharpquestionc++com
10 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E Offline
    E Offline
    EdgarBM
    wrote on last edited by
    #1

    Hi, I have an old DLL developped on VC++ 6.0. It was designed to work with VB and VC code. The problem always has been two special parameters which where an array of vaules. One was an array of doubles and the other an array of strings. It was hard, but I solved it using the SAFEARRAY structure, this way: Method (..., SAFEARRAY FAR *doubleArray, SAFEARRAY FAR *stringArray, ...) -> To call the library from VB code I only should do: Dim dbArray() as double Dim stArray() as string Redim dbArray(5) dbArray(0) = 3.4 ... 'and so to strings ->To call it from VC it was more difficult: char sMatriz[1][256/*128x2, chars doubled!*/]; strcpy (sMatriz[0], "H E L L O "); //the space represents the NULL between the string characters due to compatibility with COM ; not for doubles array LPSAFEARRAY sS = new struct tagSAFEARRAY; sS->pvData=sMatriz; sS->rgsabound->cElements = 1; //...and I passed the reference of the LPSAFEARRAY: Method (..., &sD, &sS, ...) THE PROBLEM: --------------------- Now I want this library to be used on C# or VB.NET, but I don't know the way to instantiate and pass those parameters. Any chance I get an exception like this: System.NullReferenceException Exception Details: Object reference not set to an instance of an object. I pass those parameters like: string[] sA = new string[5]; double[] dA = new double[5]; Method (..., dA, sA,...) ...and if I modify the library taking out those params (ignoring them), everything works fine. Does anyone knew how can I solve this problem? Is there any special way to pass those parameters?, anything before changing the library? I really need those params in the library! Thank you in advance, (thanks if you read all the text!) Edgar Edgar Berengena Moreno Software Engineer Appeyron Research

    S L 2 Replies Last reply
    0
    • E EdgarBM

      Hi, I have an old DLL developped on VC++ 6.0. It was designed to work with VB and VC code. The problem always has been two special parameters which where an array of vaules. One was an array of doubles and the other an array of strings. It was hard, but I solved it using the SAFEARRAY structure, this way: Method (..., SAFEARRAY FAR *doubleArray, SAFEARRAY FAR *stringArray, ...) -> To call the library from VB code I only should do: Dim dbArray() as double Dim stArray() as string Redim dbArray(5) dbArray(0) = 3.4 ... 'and so to strings ->To call it from VC it was more difficult: char sMatriz[1][256/*128x2, chars doubled!*/]; strcpy (sMatriz[0], "H E L L O "); //the space represents the NULL between the string characters due to compatibility with COM ; not for doubles array LPSAFEARRAY sS = new struct tagSAFEARRAY; sS->pvData=sMatriz; sS->rgsabound->cElements = 1; //...and I passed the reference of the LPSAFEARRAY: Method (..., &sD, &sS, ...) THE PROBLEM: --------------------- Now I want this library to be used on C# or VB.NET, but I don't know the way to instantiate and pass those parameters. Any chance I get an exception like this: System.NullReferenceException Exception Details: Object reference not set to an instance of an object. I pass those parameters like: string[] sA = new string[5]; double[] dA = new double[5]; Method (..., dA, sA,...) ...and if I modify the library taking out those params (ignoring them), everything works fine. Does anyone knew how can I solve this problem? Is there any special way to pass those parameters?, anything before changing the library? I really need those params in the library! Thank you in advance, (thanks if you read all the text!) Edgar Edgar Berengena Moreno Software Engineer Appeyron Research

      S Offline
      S Offline
      Stephane Rodriguez
      wrote on last edited by
      #2

      A SAFEARRAY in C++ like this :

      HRESULT GetItems([in] BSTR bstrLocation, [out] SAFEARRAY(VARIANT)* pItems);

      is marshalled back and forth with C# declaration like this in your interface :

      [ComImport]
      [Guid("73EB4AF8-BE9C-4b49-B3A4-24F4FF657B26")]
      public interface IMyStorage
      {
      [DispId(2)]
      void GetItems( [In, MarshalAs( UnmanagedType.BStr )] String bstrLocation,
      [Out, MarshalAs( UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT )] out Object[] Items );

      ...
      }

      Further details.


      And I swallow a small raisin.

      E 1 Reply Last reply
      0
      • S Stephane Rodriguez

        A SAFEARRAY in C++ like this :

        HRESULT GetItems([in] BSTR bstrLocation, [out] SAFEARRAY(VARIANT)* pItems);

        is marshalled back and forth with C# declaration like this in your interface :

        [ComImport]
        [Guid("73EB4AF8-BE9C-4b49-B3A4-24F4FF657B26")]
        public interface IMyStorage
        {
        [DispId(2)]
        void GetItems( [In, MarshalAs( UnmanagedType.BStr )] String bstrLocation,
        [Out, MarshalAs( UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT )] out Object[] Items );

        ...
        }

        Further details.


        And I swallow a small raisin.

        E Offline
        E Offline
        EdgarBM
        wrote on last edited by
        #3

        Thanks, ...but I can't improve anything with this! I'm trying to pass an Object[] to the library but I'm still getting the same exception. Is there anymore information or runnig sample which solves this problem?, does anyone know it?? Thank you again, Edgar Edgar Berengena Moreno Software Engineer Appeyron Research

        S 1 Reply Last reply
        0
        • E EdgarBM

          Thanks, ...but I can't improve anything with this! I'm trying to pass an Object[] to the library but I'm still getting the same exception. Is there anymore information or runnig sample which solves this problem?, does anyone know it?? Thank you again, Edgar Edgar Berengena Moreno Software Engineer Appeyron Research

          S Offline
          S Offline
          Stephane Rodriguez
          wrote on last edited by
          #4

          Can you try the following code :

          string[] MyString = {"Hello", "and", "welcome", "to", "my" , "world!"};

          I am not sure the exception you have is a marshalling issue.


          And I swallow a small raisin.

          E 1 Reply Last reply
          0
          • E EdgarBM

            Hi, I have an old DLL developped on VC++ 6.0. It was designed to work with VB and VC code. The problem always has been two special parameters which where an array of vaules. One was an array of doubles and the other an array of strings. It was hard, but I solved it using the SAFEARRAY structure, this way: Method (..., SAFEARRAY FAR *doubleArray, SAFEARRAY FAR *stringArray, ...) -> To call the library from VB code I only should do: Dim dbArray() as double Dim stArray() as string Redim dbArray(5) dbArray(0) = 3.4 ... 'and so to strings ->To call it from VC it was more difficult: char sMatriz[1][256/*128x2, chars doubled!*/]; strcpy (sMatriz[0], "H E L L O "); //the space represents the NULL between the string characters due to compatibility with COM ; not for doubles array LPSAFEARRAY sS = new struct tagSAFEARRAY; sS->pvData=sMatriz; sS->rgsabound->cElements = 1; //...and I passed the reference of the LPSAFEARRAY: Method (..., &sD, &sS, ...) THE PROBLEM: --------------------- Now I want this library to be used on C# or VB.NET, but I don't know the way to instantiate and pass those parameters. Any chance I get an exception like this: System.NullReferenceException Exception Details: Object reference not set to an instance of an object. I pass those parameters like: string[] sA = new string[5]; double[] dA = new double[5]; Method (..., dA, sA,...) ...and if I modify the library taking out those params (ignoring them), everything works fine. Does anyone knew how can I solve this problem? Is there any special way to pass those parameters?, anything before changing the library? I really need those params in the library! Thank you in advance, (thanks if you read all the text!) Edgar Edgar Berengena Moreno Software Engineer Appeyron Research

            L Offline
            L Offline
            leppie
            wrote on last edited by
            #5

            Hi maybe I can help. 1. Create arrays, like normal 2. Before calling function, foreach array, allocate mem, copy array to pointer and pass the pointer. 3. when the array returns copy the pointer back to the array. For example: From MDSN

              // array ByRef 
              int\[\] array2 = new int\[ 10 \];
              int size = array2.Length;
            
              IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( size ) 
                 \* array2.Length ); // or Marshal.AllocHGlobal (COM or not)
              Marshal.Copy( array2, 0, buffer, array2.Length );
              
              int sum2 = LibWrap.TestRefArrayOfInts( ref buffer, ref size ); // replace this with your function replaceing arrays with IntPtr
            
              if( size > 0 )
              {
                 int\[\] arrayRes = new int\[ size \];
                 Marshal.Copy( buffer, arrayRes, 0, size );
                 Marshal.FreeCoTaskMem( buffer ); //or Marshal.FreeHGlobal
              }  
            

            Now just do this to each array. Unfortunately u dont give the whole function as defined in a header file, so I cant gaurentee this will work, but it works in my case when normal marshalling wouldnt work :) Hope this helps MYrc : A .NET IRC client with C# Plugin Capabilities. See http://sourceforge.net/projects/myrc for more info. :-D

            E 1 Reply Last reply
            0
            • S Stephane Rodriguez

              Can you try the following code :

              string[] MyString = {"Hello", "and", "welcome", "to", "my" , "world!"};

              I am not sure the exception you have is a marshalling issue.


              And I swallow a small raisin.

              E Offline
              E Offline
              EdgarBM
              wrote on last edited by
              #6

              Thank you, Stephane, but It doesn't work. I always thought this was the correct solution, but it gaves me the System.NullReferenceException exception. If you have any other idea, please let me know. Thank you, Edgar Edgar Berengena Moreno Software Engineer Appeyron Research

              1 Reply Last reply
              0
              • L leppie

                Hi maybe I can help. 1. Create arrays, like normal 2. Before calling function, foreach array, allocate mem, copy array to pointer and pass the pointer. 3. when the array returns copy the pointer back to the array. For example: From MDSN

                  // array ByRef 
                  int\[\] array2 = new int\[ 10 \];
                  int size = array2.Length;
                
                  IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( size ) 
                     \* array2.Length ); // or Marshal.AllocHGlobal (COM or not)
                  Marshal.Copy( array2, 0, buffer, array2.Length );
                  
                  int sum2 = LibWrap.TestRefArrayOfInts( ref buffer, ref size ); // replace this with your function replaceing arrays with IntPtr
                
                  if( size > 0 )
                  {
                     int\[\] arrayRes = new int\[ size \];
                     Marshal.Copy( buffer, arrayRes, 0, size );
                     Marshal.FreeCoTaskMem( buffer ); //or Marshal.FreeHGlobal
                  }  
                

                Now just do this to each array. Unfortunately u dont give the whole function as defined in a header file, so I cant gaurentee this will work, but it works in my case when normal marshalling wouldnt work :) Hope this helps MYrc : A .NET IRC client with C# Plugin Capabilities. See http://sourceforge.net/projects/myrc for more info. :-D

                E Offline
                E Offline
                EdgarBM
                wrote on last edited by
                #7

                Thanks for your reply, Leppie. The only problem is that I'm working with string arrays too, so the Copy method of Marshall can't be applied. I can't say if it works or doesn't work because I need to manage the string array too so keeps receiving the exception...although it seems to work for the double[] (maybe I hope)!! Any idea for the string array? PS: the unmanaged DLL parameters (VC++ 6.0 DLL) are defined as SAFEARRAY FAR *doubleArray, SAFEARRAY FAR *stringArray ...these are the conflicting ones. Thank you again, Edgar Edgar Berengena Moreno Software Engineer Appeyron Research

                L 1 Reply Last reply
                0
                • E EdgarBM

                  Thanks for your reply, Leppie. The only problem is that I'm working with string arrays too, so the Copy method of Marshall can't be applied. I can't say if it works or doesn't work because I need to manage the string array too so keeps receiving the exception...although it seems to work for the double[] (maybe I hope)!! Any idea for the string array? PS: the unmanaged DLL parameters (VC++ 6.0 DLL) are defined as SAFEARRAY FAR *doubleArray, SAFEARRAY FAR *stringArray ...these are the conflicting ones. Thank you again, Edgar Edgar Berengena Moreno Software Engineer Appeyron Research

                  L Offline
                  L Offline
                  leppie
                  wrote on last edited by
                  #8

                  Hi try this, glad to see double[] works :) Try this:

                  ArrayList tags = new ArrayList();
                  do
                  {
                  string tag = Marshal.PtrToStringUni(ptag);
                  // ptag is pointer to string[], make sure about unicode/ansi, i assume unicode
                  if (tag == "") break;
                  else
                  {
                  tags.Add(tag);
                  ptag = new IntPtr(ptag.ToInt32() + Marshal.SizeOf(tag));
                  }
                  }
                  while(true);

                  This reversse can be done if u need to "feed" the function with the string[]. Hope this works MYrc : A .NET IRC client with C# Plugin Capabilities. See http://sourceforge.net/projects/myrc for more info. :-D

                  E 1 Reply Last reply
                  0
                  • L leppie

                    Hi try this, glad to see double[] works :) Try this:

                    ArrayList tags = new ArrayList();
                    do
                    {
                    string tag = Marshal.PtrToStringUni(ptag);
                    // ptag is pointer to string[], make sure about unicode/ansi, i assume unicode
                    if (tag == "") break;
                    else
                    {
                    tags.Add(tag);
                    ptag = new IntPtr(ptag.ToInt32() + Marshal.SizeOf(tag));
                    }
                    }
                    while(true);

                    This reversse can be done if u need to "feed" the function with the string[]. Hope this works MYrc : A .NET IRC client with C# Plugin Capabilities. See http://sourceforge.net/projects/myrc for more info. :-D

                    E Offline
                    E Offline
                    EdgarBM
                    wrote on last edited by
                    #9

                    Hi, I'm trying your second code but I'm having problems and I don't know if I'm doing it quite well. That's what I'm trying now: For the double[]: IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( cantidad ) * sVN.Length); // or Marshal.AllocHGlobal (COM or not) Marshal.Copy( sVN, 0, buffer, sVN.Length ); ...and for the string[]: IntPtr ptag = new IntPtr (); ptag = Marshal.StringToHGlobalAnsi ("maybe..."); ArrayList tags = new ArrayList(); do { string tag = Marshal.PtrToStringAnsi (ptag); //PtrToStringUni (ptag); // ptag is pointer to string[], make sure about unicode/ansi, i assume unicode if (tag == "") break; else { tags.Add(tag); ptag = new IntPtr(ptag.ToInt32() + Marshal.SizeOf(Marshal.StringToHGlobalAnsi (tag))); } }while(true); And I define the DLL Function like: Method (..., ref IntPtr sbufN, ArrayList sbufC, ...); What am I doing wrong? Thank you again for your dedication, Edgar __________________________________________ Edgar Berengena Moreno Software Engineer Appeyron Research

                    L 1 Reply Last reply
                    0
                    • E EdgarBM

                      Hi, I'm trying your second code but I'm having problems and I don't know if I'm doing it quite well. That's what I'm trying now: For the double[]: IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( cantidad ) * sVN.Length); // or Marshal.AllocHGlobal (COM or not) Marshal.Copy( sVN, 0, buffer, sVN.Length ); ...and for the string[]: IntPtr ptag = new IntPtr (); ptag = Marshal.StringToHGlobalAnsi ("maybe..."); ArrayList tags = new ArrayList(); do { string tag = Marshal.PtrToStringAnsi (ptag); //PtrToStringUni (ptag); // ptag is pointer to string[], make sure about unicode/ansi, i assume unicode if (tag == "") break; else { tags.Add(tag); ptag = new IntPtr(ptag.ToInt32() + Marshal.SizeOf(Marshal.StringToHGlobalAnsi (tag))); } }while(true); And I define the DLL Function like: Method (..., ref IntPtr sbufN, ArrayList sbufC, ...); What am I doing wrong? Thank you again for your dedication, Edgar __________________________________________ Edgar Berengena Moreno Software Engineer Appeyron Research

                      L Offline
                      L Offline
                      leppie
                      wrote on last edited by
                      #10

                      HoHa what a mess :) Method (..., IntPtr sbufN, IntPtr sbufC, ...);

                      string[] strarr = new string[]{"one","two","three","four"};
                      IntPtr firstpointer;
                      int counter = 0;
                      foreach (string str in strarr)
                      {
                      IntPtr ptr = Marshal.StringToHGlobalUni(str);
                      if (counter++ == 0) firstpointer = ptr;
                      }

                      Method(..., IntPtr sbufN, firstpointer,...);

                      for (int i = 0; i < strarr.Length; i++)
                      {
                      strarr[i] = Marshal.PtrToStringUni(firstpointer);
                      firstpointer = new IntPtr(firstpointer.ToInt32() + Marshal.SizeOf(strarr[i]));
                      }

                      Ok try that :) Like I said it is very important to know whether the function will need values from the string array when passing it to the function. What is the function to do / return with the string[] ??? MYrc : A .NET IRC client with C# Plugin Capabilities. See http://sourceforge.net/projects/myrc for more info. :-D

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups