Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

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

Marshal array of strings

Hi, I have a function in unmanaged C++ dll that needs to return an array of fileNames;
it is defined like this:
void NajdiSlicni (char* imeSkeleton, char** rezultati)
where rezultati is the place where all the fileNames should be

Can you give me code how to import this function in C# with marshaling?
Can you tell me how to fill the rezultati variable?

Thanks in advance




I have read but it doesn't work
http://msdn2.microsoft.com/en-us/library/hk9wyw21(vs.80).aspx
0
Dimkov
Asked:
Dimkov
  • 8
  • 6
1 Solution
 
felipecslCommented:
You can declare this in C# as:

[(DllImport="myDllFIle.dll")]
private static void NajdiSlicni (string imeSkeleton, string[] rezultati);

In other words, the result would be an array of strings - string[] (the same as char** in c++)

Hope that helps!
0
 
felipecslCommented:
If I understood your second question, you could declare your result variable as a basic_string<string>. Go pushing back the strings to the result array and when you have to return it, try return myResult.c_str();
That should work.
0
 
DimkovAuthor Commented:
the function should return something like:

rezultati[0] ="firstString";
rezultati[1] ="secondtString";
rezultati[2] ="thirdString";
rezultati[3] ="forthString";
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
DimkovAuthor Commented:
I found a go around;
I decided to make the funciont simpler:
void NajdiSlicni (char* imeSkeleton, char* rezultati)
where rezultati will be: "firstString;secondtString;thirdString;forthString"

the problem is, when I get out of the solution, I rezultati returns its previous values
0
 
felipecslCommented:
What do you mean by "its previous values"?
0
 
DimkovAuthor Commented:
in C# i set the value of string str;

string str="AAAAAAAAAAAAAAA";
NajdiSlicni (firstVariable,str);


in C++ when I enter the function NajdiSlicni (char * firstVariable, char* rezultati)

rezultati has the value "AAAAAAAAAAAAAAA".

Here I change the value to "firstString;secondtString;thirdString;forthString"

when the code returns to C#

the str remains  "AAAAAAAAAAAAAAA".
0
 
felipecslCommented:
ahh.. sure, you need to declare the rezultati as by ref. Follow the signature:

private static void NajdiSlicni (string imeSkeleton, string ref rezultati);

This should return to C# the value you just set in C++. Then, back in C# you can parse the results with a string.Split(';') or so.
Please reply back with feedback.
0
 
DimkovAuthor Commented:
rezultati becomes empty.
I believe there is some trick with using managed to unmanaged memory. I think I sow some other functions in marshall than can help....
will check them. If you find somethin please write
0
 
felipecslCommented:
try with with the "out" keyword instead of "ref". Like this:

private static void NajdiSlicni (string imeSkeleton, out string rezultati);

But I was quite sure the ref would work fine... I've already done this kind of call when calling Win32 APi functions from C#, so I believe there may be something wrong with your c++ code that returns the resultati.
0
 
DimkovAuthor Commented:
Here is the code.. hope it helps

void NajdiSlicni (char* imeSkeleton,wchar_t * rezultati)
{
      code...

      for (int i=0;i<10;i++)
      {

            string temp;
            temp=vect[i].second;
            temp.append(";");
            wchar_t *p=new wchar_t[temp.length()];
            for(string::size_type i=0; i<temp.length()+1; ++i)
            p[i]=temp[i];
            wcscat(rezultati,p);
      }  
}

       private void CompareBtn_Click(object sender, EventArgs e)
        {
            string str=("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC");
             Algorithm.NajdiSlicni(targetFile.Text, ref str);
            string[] nov=str.Split(';');
       }

        [DllImport("Algoritam.dll")]
        public static extern void NajdiSlicni([MarshalAs(UnmanagedType.LPStr)] string str, ref string stringovi);

In the previous work, have you just send strings, or the C++ code changed the strings
0
 
felipecslCommented:
gimme some minutes, I'll try to implement it
0
 
felipecslCommented:
here is the code you need.

C#
[DllImport("cpptest.dll", EntryPoint = "?fncpptest@@YAHPADPAH@Z")]
public static extern int fncpptest(
      IntPtr _sResult,
      out int _nLength);

static void Main()
{
      int maxStringSize = 255;
      IntPtr ptrString = Marshal.AllocHGlobal(maxStringSize);
      int l_nStrSize;

      fncpptest(ptrString, out l_nStrSize);
      string result = Marshal.PtrToStringAnsi(ptrString, l_nStrSize);

}

C++
__declspec(dllexport) int fncpptest(
      char *_sResult,
      int *_nSize)
{
      memcpy(_sResult, "some string for c#", 18);
      (*_nSize) = 18;
      return 1;
}
0
 
felipecslCommented:
if you change the C++ exported function signature, you'll have to replace the entry point in the C# DllImport. You can get this string in the dependency walker tool (http://www.dependencywalker.com/)

Please tell me if this fits your needs
0
 
DimkovAuthor Commented:
Briliant
Thanks felipecsl
0

Featured Post

Free recovery tool for Microsoft Active Directory

Veeam Explorer for Microsoft Active Directory provides fast and reliable object-level recovery for Active Directory from a single-pass, agentless backup or storage snapshot — without the need to restore an entire virtual machine or use third-party tools.

  • 8
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now